// 版权所有2009 Go作者。保留所有权利。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

// HTTP服务器。参见RFC 7230至7235。

package http

import (
	"bufio"
	"bytes"
	"context"
	"crypto/tls"
	"errors"
	"fmt"
	"internal/godebug"
	"io"
	"log"
	"math/rand"
	"net"
	"net/textproto"
	"net/url"
	urlpkg "net/url"
	"path"
	"runtime"
	"sort"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"time"

	"golang.org/x/net/http/httpguts"
)

// HTTP服务器使用的错误。
var (
	// errbody notallowed由ResponseWriter返回。当HTTP方法或响应代码不允许
	// 。
	// 正文时，Write调用
	ErrBodyNotAllowed = errors.New("http: request method or response status code does not allow body")

	// 错误劫持由ResponseWriter返回。当
	// 使用
	// 劫持器接口劫持基础连接时编写调用。对被劫持的
	// 连接执行零字节写入操作将返回errjacked，而不会产生任何其他副作用。
	ErrHijacked = errors.New("http: connection has been hijacked")

	// ErrContentLength由ResponseWriter返回。当处理程序使用
	// 。
	// 声明的大小设置内容长度响应头，然后尝试写入比
	// 声明的字节更多的字节时，Write调用
	ErrContentLength = errors.New("http: wrote more than the declared Content-Length")

	// 已弃用：ErrWriteAfterFlush不再由
	// 返回net/http包中的任何内容。调用方不应
	// 将错误与此变量进行比较。
	ErrWriteAfterFlush = errors.New("unused")
)

// 处理程序响应HTTP请求。
// 
// ServeHTTP应该将回复头和数据写入响应编写器
// 然后返回。返回请求完成的信号；
// 使用响应编写器或读取
// 请求无效。在
// ServeHTTP调用完成后或同时执行。
// 
// 根据HTTP客户端软件、HTTP协议版本和
// 客户端和Go服务器之间的任何中介，可能无法读取请求。写信给
// 回复作者后的正文。谨慎的处理者应该阅读请求。正文
// 首先，然后回复。
// 
// 除读取正文外，处理程序不应修改
// 提供的请求。
// 
// 如果ServeHTTP崩溃，服务器（ServeHTTP的调用方）会假定崩溃的影响与活动请求无关。
// 它恢复死机，将堆栈跟踪记录到服务器错误日志，
// 并根据HTTP协议关闭网络连接或发送HTTP/2 
// RST_流。要中止处理程序，使
// 客户端看到中断的响应，但服务器不记录
// 错误，请使用ErrAbortHandler值。
type Handler interface {
	ServeHTTP(ResponseWriter, *Request)
}

// HTTP处理程序使用ResponseWriter接口来构造HTTP响应。
// 
// 在处理程序之后不能使用ResponseWriter。ServeHTTP方法
// 已返回。
type ResponseWriter interface {
	// Header返回将由
	// WriteHeader发送的头映射。头映射也是
	// 处理程序设置HTTP尾部的机制。
	// 
	// 在调用WriteHeader（或
	// Write）后更改头映射无效，除非修改的头是
	// 。gong zuo jian defg
	// 键被视为
	// 键。看看这个例子。第二种方法是，对于在第一次写入之后处理程序才知道的尾部
	// 密钥，
	// 是使用TrailerPrefix 
	// 常量值作为头映射密钥的前缀。参见TrailerPrefix。
	// 
	// 要抑制自动响应头（例如“日期”），请将
	// 其值设置为零。
	Header() Header

	// Write将数据作为HTTP应答的一部分写入连接。
	// 
	// 如果尚未调用WriteHeader，则在写入数据之前，Write将调用
	// WriteHeader（http.StatusOK）。如果头
	// 不包含内容类型行，Write会将内容类型集
	// 添加到将写入数据的初始512字节传递给
	// DetectContentType的结果中。此外，如果所有写入的
	// 数据的总大小小于几KB，并且没有刷新调用，
	// 自动添加内容长度标题。
	// 
	// 根据HTTP协议版本和客户端，调用
	// Write或WriteHeader可能会阻止将来对
	// 请求的读取。身体对于HTTP/1。x请求，处理程序应该在写入响应之前读取任何
	// 所需的请求正文数据。一旦清除了
	// 头（由于显式清除器.Flush 
	// 调用或写入足够的数据以触发清除），请求主体
	// 可能不可用。对于HTTP/2请求，Go HTTP服务器允许
	// 处理程序继续读取请求正文，同时
	// 写入响应。但是，所有HTTP/2客户端可能都不支持这种行为。如果
	// 可以最大限度地提高兼容性，则处理程序应该在写入之前读取。
	Write([]byte) (int, error)

	// WriteHeader发送一个HTTP响应头，其中包含提供的
	// 状态代码。
	// 
	// 如果未显式调用WriteHeader，第一次调用Write 
	// 将触发隐式WriteHeader（http.StatusOK）。因此，对WriteHeader的显式调用主要用于发送错误代码。
	// 
	// 提供的代码必须是有效的HTTP 1x-5xx状态代码。
	// 只能写入一个标题。Go目前不支持发送用户定义的1xx信息头，
	// 但
	// 服务器在请求时自动发送的100 continue响应头除外。身体被阅读。
	WriteHeader(statusCode int)
}

// Flusher接口由响应编写器实现，它允许HTTP处理程序将缓冲数据刷新到客户端。
// 
// 默认的HTTP/1。x和HTTP/2 ResponseWriter实现
// 支持Flusher，但ResponseWriter包装可能不支持。处理程序
// 应始终在运行时测试此功能。
// 
// 请注意，即使对于支持Flush的响应编写器，
// 如果客户端通过HTTP代理连接，
// 在响应
// 完成之前，缓冲数据可能无法到达客户端。
type Flusher interface {
	// Flush将所有缓冲数据发送到客户端。
	Flush()
}

// 劫持者接口由响应编写器实现，它允许一个HTTP处理程序接管连接。
// 
// HTTP/1的默认响应编写器。x连接支持
// 劫持者，但HTTP/2连接故意不支持。
// ResponseWriter包装可能也不支持劫机者。处理程序
// 应始终在运行时测试此功能。
type Hijacker interface {
	// 劫持让调用方接管连接。
	// 在调用劫持HTTP服务器库后，
	// 将不会对连接执行任何其他操作。
	// 
	// 呼叫方负责管理
	// 并关闭连接。
	// 
	// 返回的网络。根据
	// 了。呼叫方有责任设定
	// 服务器的配置，Conn可能已经设置了读写截止日期
	// 或根据需要清除这些截止日期。
	// 
	// 返回的bufio。读卡器可能包含来自客户端的未经处理的缓冲
	// 数据。
	// 
	// 呼叫劫持后，原始请求。禁止使用
	// 车身。原始请求的上下文保持有效，并且在请求的ServeHTTP方法
	// 。
	// 返回之前，不会取消
	Hijack() (net.Conn, *bufio.ReadWriter, error)
}

// CloseNotifier接口由ResponseWriter实现，它允许检测底层连接何时消失。
// 
// 如果客户端在响应准备就绪之前已断开连接，则此机制可用于取消服务器上的长时间操作
// 。
// 
// 已弃用：CloseNotifier接口早于Go的上下文包。
// 新代码应该使用请求。而是上下文。
type CloseNotifier interface {
	// CloseNotify返回一个通道，当客户端连接断开时，该通道最多接收一个
	// 单个值（true）。
	// 
	// CloseNotify可能会等待通知，直到收到请求。正文已全部阅读。
	// 
	// 处理程序返回后，无法保证
	// 通道会收到一个值。
	// 
	// 如果协议是HTTP/1.1，在
	// 处理幂等请求（这样的GET）时调用CloseNotify，而
	// HTTP/1.1管道正在使用，则后续
	// 管道化请求的到达可能会导致在
	// 返回通道上发送值。实际上，HTTP/1.1管道并不是在浏览器中启用的，在野外也不常见。如果此
	// 有问题，请在方法
	// 如POST上使用HTTP/2或仅使用CloseNotify。
	CloseNotify() <-chan bool
}

var (
	// ServerContextKey是一个上下文键。它可以在HTTP 
	// 上下文处理程序中使用。值来访问
	// 启动处理程序的服务器。关联的值将为
	// 类型*服务器。
	ServerContextKey = &contextKey{"http-server"}

	// LocalAddrContextKey是一个上下文键。它可以在
	// HTTP处理程序中与上下文一起使用。值访问本地
	// 连接到达的地址。
	// 关联的值将是net类型。地址。
	LocalAddrContextKey = &contextKey{"local-addr"}
)

// conn代表HTTP连接的服务器端。
type conn struct {
	// 服务器是连接到达的服务器。
	// 不可变；永远不要零。
	server *Server

	// cancelCtx取消连接级别上下文。
	cancelCtx context.CancelFunc

	// rwc是底层网络连接。
	// 这永远不会被其他类型包装，而是向CloseNotifier调用者提供的值。它通常是*net类型。TCPConn或
	// /*tls。Conn.
	rwc net.Conn

	// remoteAddr是rwc。RemoteAddr（）。字符串（）。它不是在侦听器的Accept goroutine中同步填充的，因为有些实现会阻塞它。
	// 它直接在（*conn）内部填充。给戈鲁廷上菜。
	// 这是处理程序（*请求）的值。远程地址。
	remoteAddr string

	// tlsState是使用TLS时的TLS连接状态。
	// nil表示不是TLS。
	tlsState *tls.ConnectionState

	// werr设置为rwc的第一个写入错误。
	// 通过checkConnErrorWriter{w}设置，bufw在其中写入。
	werr error

	// r是bufr的读取源。它是rwc的包装，提供
	// io。LimitedReader样式限制（在读取请求头时）
	// 以及支持CloseNotifier的功能。参见*康纳读者文档。
	r *connReader

	// bufr从r读取。
	bufr *bufio.Reader

	// bufw写入checkConnErrorWriter{c}，后者在错误时填充werr。
	bufw *bufio.Writer

	// lastMethod是此连接上的最新请求
	// 的方法（如果有）。
	lastMethod string

	curReq atomic.Value // of*response（其中包含一个请求）

	curState struct{ atomic uint64 } // packed（unixtime<<8|uint8（ConnState））

	// mu guards hickedV 
	mu sync.Mutex

	// hickedV是指此连接是否已被具有Hicker接口的处理程序劫持
	// 。
	// 由mu守卫。
	hijackedv bool
}

func (c *conn) hijacked() bool {
	c.mu.Lock()
	defer c.mu.Unlock()
	return c.hijackedv
}

// c.mu必须持有。
func (c *conn) hijackLocked() (rwc net.Conn, buf *bufio.ReadWriter, err error) {
	if c.hijackedv {
		return nil, nil, ErrHijacked
	}
	c.r.abortPendingRead()

	c.hijackedv = true
	rwc = c.rwc
	rwc.SetDeadline(time.Time{})

	buf = bufio.NewReadWriter(c.bufr, bufio.NewWriter(rwc))
	if c.r.hasByte {
		if _, err := c.bufr.Peek(c.bufr.Buffered() + 1); err != nil {
			return nil, nil, fmt.Errorf("unexpected Peek failure reading buffered byte: %v", err)
		}
	}
	c.setState(rwc, StateHijacked, runHooks)
	return
}

// 对于DetectContentType，这应该是>=512字节，但是如果不是这样的话，它有点随意。
const bufferBeforeChunkingSize = 2048

// chunkWriter写入响应的conn缓冲区，写入程序
// 被响应包装。w缓冲写入程序。
// 
// chunkWriter还负责完成标题，包括
// 有条件地设置内容类型并设置内容长度
// 如果处理程序的最终输出小于缓冲区
// 大小。在分块模式下，它还会有条件地添加分块头。
// 
// 参见上述评论（*回复）。为整个写入流进行写入。
type chunkWriter struct {
	res *response

	// 在res.writeHeader时，如果调用了res.writeHeader，并且正在进行额外的缓冲来计算
	// 内容类型和/或内容长度，则header是nil或res.handlerHeader的深层克隆。
	header Header

	// wroteHeader告诉我们头是否被写入了“the 
	// wire”（或者更确切地说：w.conn.buf）。这与
	// /（*响应）不同。wroteHeader，它只告诉您它是否是
	// 逻辑编写的。
	wroteHeader bool

	// 由writeHeader方法设置：
	chunking bool // 对回复正文使用分块传输编码
}

var (
	crlf       = []byte("\r\n")
	colonSpace = []byte(": ")
)

func (cw *chunkWriter) Write(p []byte) (n int, err error) {
	if !cw.wroteHeader {
		cw.writeHeader(p)
	}
	if cw.res.req.Method == "HEAD" {
		// Eat写入。
		return len(p), nil
	}
	if cw.chunking {
		_, err = fmt.Fprintf(cw.res.conn.bufw, "%x\r\n", len(p))
		if err != nil {
			cw.res.conn.rwc.Close()
			return
		}
	}
	n, err = cw.res.conn.bufw.Write(p)
	if cw.chunking && err == nil {
		_, err = cw.res.conn.bufw.Write(crlf)
	}
	if err != nil {
		cw.res.conn.rwc.Close()
	}
	return
}

func (cw *chunkWriter) flush() {
	if !cw.wroteHeader {
		cw.writeHeader(nil)
	}
	cw.res.conn.bufw.Flush()
}

func (cw *chunkWriter) close() {
	if !cw.wroteHeader {
		cw.writeHeader(nil)
	}
	if cw.chunking {
		bw := cw.res.conn.bufw // 康涅狄格州的bufio编剧
		// 零块标记EOF 
		bw.WriteString("0\r\n")
		if trailers := cw.res.finalTrailers(); trailers != nil {
			trailers.Write(bw) // 编剧处理注意错误
		}
		// 预告片后的最后一个空行
		// 是否存在）
		bw.WriteString("\r\n")
	}
}

// 响应表示HTTP响应的服务器端。wen jian feg
type response struct {
	conn             *conn
	reqBody          io.ReadCloser

	// 表示是否可以将100 Continue头写入连接
	// 中。
	// 写入头时必须保持writeContinueMu。
	// 这两个字段一起同步正文读取器
	// （expectContinueReader，它想写100 Continue）
	// 与主编写器。
	canWriteContinue atomicBool
	writeContinueMu  sync.Mutex

	w  *bufio.Writer // 缓冲区以块的形式输出到chunkWriter 
	cw chunkWriter

	// handlerHeader是处理程序可以访问的头，
	// 即使在WriteHeader之后，它也可能被保留和变异。
	// handlerHeader被复制到cw中。在WriteHeader 
	// 时间的头，并在此后私下进行了变异。
	handlerHeader Header
	calledHeader  bool // 处理程序通过标头访问handlerHeader 

	written       int64 // 写入正文的字节数
	contentLength int64 // 显式声明的内容长度；或-1 
	status        int   // 状态码传递给写头

	// 在回复后关闭连接。如果存在
	// “Connection:keep alive”响应头和
	// 内容长度，则应请求设置并在处理程序响应后更新。
	closeAfterReply bool

	// requestBodyLimitHit由requestTooLarge在
	// MaxByteReader达到其最大大小时设置。它在
	// WriteHeader中进行检查，以确保我们不会使用
	// 剩余的请求正文来尝试前进到下一个HTTP 
	// 请求。相反，当设置此选项时，我们将停止读取此连接上的后续请求，并停止从中读取
	// 输入。
	requestBodyLimitHit bool

	// trailes是处理程序完成正文编写后要发送的头文件。当响应头为
	// 拖车响应头初始化。
	// 写入时，此字段由
	trailers []string

	handlerDone atomicBool // 当处理程序退出时设置为true 

	// 缓冲日期、内容长度和状态代码
	dateBuf   [len(TimeFormat)]byte
	clenBuf   [10]byte
	statusBuf [3]byte

	// closeNotifyCh是CloseNotify返回的通道。
	// TODO（bradfitz）：目前（对于Go 1.8）总是
	// non-nil。让这个懒散地重新创建，就像以前一样？
	closeNotifyCh  chan bool
	didCloseNotify int32 // atomic（只有0->1个获胜者应该发送）
}

// TrailerPrefix是ResponseWriter的神奇前缀。Header map key 
// 如果存在，则表示map条目实际上是针对
// 响应预告片的，而不是响应头。ServeHTTP调用完成后，前缀
// 被剥离，值被发送到预告片中。
// 
// 此机制仅适用于在写入标题之前未知的拖车
// 。如果拖车组是固定的
// 或在写入报头之前已知，则首选正常的Go Trailes机制
// 
// https:
// https:
const TrailerPrefix = "Trailer:"

// 在处理程序退出后调用finalTrailers，如果处理程序设置了任何trailes，则返回非nil 
// 值。
func (w *response) finalTrailers() Header {
	var t Header
	for k, vv := range w.handlerHeader {
		if strings.HasPrefix(k, TrailerPrefix) {
			if t == nil {
				t = make(Header)
			}
			t[strings.TrimPrefix(k, TrailerPrefix)] = vv
		}
	}
	for _, k := range w.trailers {
		if t == nil {
			t = make(Header)
		}
		for _, v := range w.handlerHeader[k] {
			t.Add(k, v)
		}
	}
	return t
}

type atomicBool int32

func (b *atomicBool) isSet() bool { return atomic.LoadInt32((*int32)(b)) != 0 }
func (b *atomicBool) setTrue()    { atomic.StoreInt32((*int32)(b), 1) }
func (b *atomicBool) setFalse()   { atomic.StoreInt32((*int32)(b), 0) }

// 写入
// 响应头时，会为每个拖车头调用declareTrailer。它注意到，在响应末尾的预告片中需要写入
// 标题。
func (w *response) declareTrailer(k string) {
	k = CanonicalHeaderKey(k)
	if !httpguts.ValidTrailerHeader(k) {
		// RFC 7230第4.1.2节禁止
		return
	}
	w.trailers = append(w.trailers, k)
}

// 当从客户端读取了太多输入
// 时，maxBytesReader将调用requestTooLarge。
func (w *response) requestTooLarge() {
	w.closeAfterReply = true
	w.requestBodyLimitHit = true
	if !w.wroteHeader {
		w.Header().Set("Connection", "close")
	}
}

// needsSniff报告内容类型是否仍需要嗅探。
func (w *response) needsSniff() bool {
	_, haveType := w.handlerHeader["Content-Type"]
	return !w.cw.wroteHeader && !haveType && w.written < sniffLen
}

// 写入时会隐藏io。Writer value的可选ReadFrom方法
// from io。复制
type writerOnly struct {
	io.Writer
}

// ReadFrom用于优化从*操作系统的复制。将常规文件
// 发送到*net。使用sendfile的TCPConn，或来自受支持的src类型，例如
// 作为*net。Linux上带有拼接的TCPConn。
func (w *response) ReadFrom(src io.Reader) (n int64, err error) {
	bufp := copyBufPool.Get().(*[]byte)
	buf := *bufp
	defer copyBufPool.Put(bufp)

	// 我们的底层w.conn.rwc通常是一个*TCPConn（使用它的
	// 自己的ReadFrom方法）。如果没有，就回到正常的
	// 复制方法。
	rf, ok := w.conn.rwc.(io.ReaderFrom)
	if !ok {
		return io.CopyBuffer(writerOnly{w}, src, buf)
	}

	// 在切换到ReadFrom之前复制第一个sniffLen字节。
	// 这确保了我们不会在
	// 源可用（请参见golang.org/issue/5660）之前开始编写响应，并提供足够的字节，以便在需要时执行内容类型嗅探。
	if !w.cw.wroteHeader {
		n0, err := io.CopyBuffer(writerOnly{w}, io.LimitReader(src, sniffLen), buf)
		n += n0
		if err != nil || n0 < sniffLen {
			return n, err
		}
	}

	w.w.Flush()  // 清除之前的任何写入操作
	w.cw.flush() // 确保写入了头；将数据刷新到rwc 

	// 现在cw已刷新，其分块字段保证已初始化。
	if !w.cw.chunking && w.bodyAllowed() {
		n0, err := rf.ReadFrom(src)
		n += n0
		w.written += n0
		return n, err
	}

	n0, err := io.CopyBuffer(writerOnly{w}, src, buf)
	n += n0
	return n, err
}

// debugServerConnections控制是否使用详细的日志包装器包装所有服务器连接。
const debugServerConnections = false

// 从rwc创建新连接。
func (srv *Server) newConn(rwc net.Conn) *conn {
	c := &conn{
		server: srv,
		rwc:    rwc,
	}
	if debugServerConnections {
		c.rwc = newLoggingConn("server", c.rwc)
	}
	return c
}

type readResult struct {
	_   incomparable
	n   int
	err error
	b   byte // 字节读取，如果n==1 
}

// connReader是io。*conn使用的读卡器包装器。它结合了
// 选择性激活io。LimitedReader（绑定请求头
// 读取大小），支持选择性地保留io。读者读取
// 在后台goroutine中阻止调用以等待活动，
// 触发CloseNotifier通道。
type connReader struct {
	conn *conn

	mu      sync.Mutex // 
	hasByte bool
	byteBuf [1]byte
	cond    *sync.Cond
	inRead  bool
	aborted bool  // 在conn.rwc截止日期设置为过去
	remain  int64 // 剩余字节
}

func (cr *connReader) lock() {
	cr.mu.Lock()
	if cr.cond == nil {
		cr.cond = sync.NewCond(&cr.mu)
	}
}

func (cr *connReader) unlock() { cr.mu.Unlock() }

func (cr *connReader) startBackgroundRead() {
	cr.lock()
	defer cr.unlock()
	if cr.inRead {
		panic("invalid concurrent Body.Read call")
	}
	if cr.hasByte {
		return
	}
	cr.inRead = true
	cr.conn.rwc.SetReadDeadline(time.Time{})
	go cr.backgroundRead()
}

func (cr *connReader) backgroundRead() {
	n, err := cr.conn.rwc.Read(cr.byteBuf[:])
	cr.lock()
	if n == 1 {
		cr.hasByte = true
		// 我们已经超过了前一个请求的正文结尾
		// （因为我们不会在后台阅读其他内容），因此
		// 这是一个流水线HTTP请求。在Go 1.11之前，我们曾在CloseNotify频道发送
		// 并取消此处的上下文，但该行为仅记录为“may”，我们只记录了
		// 这样做，因为CloseNotify在上下文支持之前的早期Go版本中意外地表现了
		// 的行为。一旦我们添加了上下文支持，人们就会使用处理程序的请求。Context（）并传递它。在流水线HTTP请求上使用这种上下文
		// 取消会导致问题。
		// 幸运的是，几乎没有任何东西使用HTTP/1。x流水线。
		// 不幸的是，apt get可以，或者有时可以。
		// 新的Go 1.11行为：不要触发CloseNotify或取消
		// 关于流水线请求的上下文。不应该影响人们，但
		// 修复了23921号问题等案例。这意味着客户端在发送流水线
		// 请求后关闭TCP连接不会取消上下文，但我们会在任何
		// 写入失败（在checkConnErrorWriter.write中）时捕捉到这一点。
		// 如果服务器从未写入，是的，仍然存在人为的
		// 服务器和客户端行为，这无法取消
		// 上下文，但这就是HTTP/1的原因。x管道系统在
		// 无论如何都死了。
	}
	if ne, ok := err.(net.Error); ok && cr.aborted && ne.Timeout() {
		// 忽略此错误。这是
		// 另一个调用abortPendingRead的goroutine的预期错误。
	} else if err != nil {
		cr.handleReadError(err)
	}
	cr.aborted = false
	cr.inRead = false
	cr.unlock()
	cr.cond.Broadcast()
}

func (cr *connReader) abortPendingRead() {
	cr.lock()
	defer cr.unlock()
	if !cr.inRead {
		return
	}
	cr.aborted = true
	cr.conn.rwc.SetReadDeadline(aLongTimeAgo)
	for cr.inRead {
		cr.cond.Wait()
	}
	cr.conn.rwc.SetReadDeadline(time.Time{})
}

func (cr *connReader) setReadLimit(remain int64) { cr.remain = remain }
func (cr *connReader) setInfiniteReadLimit()     { cr.remain = maxInt64 }
func (cr *connReader) hitReadLimit() bool        { return cr.remain <= 0 }

// 只要从客户端读取返回
// 非零错误，就会调用handleReadError。
// 
// 提供的非零错误几乎总是io。EOF或“使用
// 封闭网络连接”。在任何情况下，这个错误都不是特别有趣的，除了开发过程中的调试。任何错误都意味着连接已断开，我们应该关闭它的上下文。
// 
// 可以从多个goroutine调用它。
func (cr *connReader) handleReadError(_ error) {
	cr.conn.cancelCtx()
	cr.closeNotify()
}

// 可以从多个goroutine调用。
func (cr *connReader) closeNotify() {
	res, _ := cr.conn.curReq.Load().(*response)
	if res != nil && atomic.CompareAndSwapInt32(&res.didCloseNotify, 0, 1) {
		res.closeNotifyCh <- true
	}
}

func (cr *connReader) Read(p []byte) (n int, err error) {
	cr.lock()
	if cr.inRead {
		cr.unlock()
		if cr.conn.hijacked() {
			panic("invalid Body.Read call. After hijacked, the original Request must not be used")
		}
		panic("invalid concurrent Body.Read call")
	}
	if cr.hitReadLimit() {
		cr.unlock()
		return 0, io.EOF
	}
	if len(p) == 0 {
		cr.unlock()
		return 0, nil
	}
	if int64(len(p)) > cr.remain {
		p = p[:cr.remain]
	}
	if cr.hasByte {
		p[0] = cr.byteBuf[0]
		cr.hasByte = false
		cr.unlock()
		return 1, nil
	}
	cr.inRead = true
	cr.unlock()
	n, err = cr.conn.rwc.Read(p)

	cr.lock()
	cr.inRead = false
	if err != nil {
		cr.handleReadError(err)
	}
	cr.remain -= int64(n)
	cr.unlock()

	cr.cond.Broadcast()
	return n, err
}

var (
	bufioReaderPool   sync.Pool
	bufioWriter2kPool sync.Pool
	bufioWriter4kPool sync.Pool
)

var copyBufPool = sync.Pool{
	New: func() any {
		b := make([]byte, 32*1024)
		return &b
	},
}

func bufioWriterPool(size int) *sync.Pool {
	switch size {
	case 2 << 10:
		return &bufioWriter2kPool
	case 4 << 10:
		return &bufioWriter4kPool
	}
	return nil
}

func newBufioReader(r io.Reader) *bufio.Reader {
	if v := bufioReaderPool.Get(); v != nil {
		br := v.(*bufio.Reader)
		br.Reset(r)
		return br
	}
	// 注意：如果此读卡器大小发生变化，请更新
	// TestHandlerBodyClose的假设。
	return bufio.NewReader(r)
}

func putBufioReader(br *bufio.Reader) {
	br.Reset(nil)
	bufioReaderPool.Put(br)
}

func newBufioWriterSize(w io.Writer, size int) *bufio.Writer {
	pool := bufioWriterPool(size)
	if pool != nil {
		if v := pool.Get(); v != nil {
			bw := v.(*bufio.Writer)
			bw.Reset(w)
			return bw
		}
	}
	return bufio.NewWriterSize(w, size)
}

func putBufioWriter(bw *bufio.Writer) {
	bw.Reset(nil)
	if pool := bufioWriterPool(bw.Available()); pool != nil {
		pool.Put(bw)
	}
}

// DefaultMaxHeaderBytes是HTTP请求中头
// 的最大允许大小。
// 这可以通过设置服务器来覆盖。MaxHeaderBytes。
const DefaultMaxHeaderBytes = 1 << 20 // 1MB 

func (srv *Server) maxHeaderBytes() int {
	if srv.MaxHeaderBytes > 0 {
		return srv.MaxHeaderBytes
	}
	return DefaultMaxHeaderBytes
}

func (srv *Server) initialReadLimitSize() int64 {
	return int64(srv.maxHeaderBytes()) + 4096 // bufio slop 
}

// tlsHandshakeTimeout返回TLS 
// 握手允许的时间限制，或零表示无限。
// 
// 返回任何正ReadHeaderTimeout、
// ReadTimeout或WriteTimeout中的最小值。
func (srv *Server) tlsHandshakeTimeout() time.Duration {
	var ret time.Duration
	for _, v := range [...]time.Duration{
		srv.ReadHeaderTimeout,
		srv.ReadTimeout,
		srv.WriteTimeout,
	} {
		if v <= 0 {
			continue
		}
		if ret == 0 || v < ret {
			ret = v
		}
	}
	return ret
}

// io的包装器。ReadCloser在第一次读取时发送
// HTTP/1.1 100 Continue头
type expectContinueReader struct {
	resp       *response
	readCloser io.ReadCloser
	closed     atomicBool
	sawEOF     atomicBool
}

func (ecr *expectContinueReader) Read(p []byte) (n int, err error) {
	if ecr.closed.isSet() {
		return 0, ErrBodyReadAfterClose
	}
	w := ecr.resp
	if !w.wroteContinue && w.canWriteContinue.isSet() && !w.conn.hijacked() {
		w.wroteContinue = true
		w.writeContinueMu.Lock()
		if w.canWriteContinue.isSet() {
			w.conn.bufw.WriteString("HTTP/1.1 100 Continue\r\n\r\n")
			w.conn.bufw.Flush()
			w.canWriteContinue.setFalse()
		}
		w.writeContinueMu.Unlock()
	}
	n, err = ecr.readCloser.Read(p)
	if err == io.EOF {
		ecr.sawEOF.setTrue()
	}
	return
}

func (ecr *expectContinueReader) Close() error {
	ecr.closed.setTrue()
	return ecr.readCloser.Close()
}

// TimeFormat是在HTTP 
// 头中生成时间时使用的时间格式。就像时间一样。RFC1123但硬编码GMT为时间
// 区域。要生成正确的格式，格式化的时间必须为UTC。
// 
// 有关解析此时间格式的信息，请参阅ParseTime。
const TimeFormat = "Mon, 02 Jan 2006 15:04:05 GMT"

// appendTime是[]字节（t.UTC（）的非分配版本。格式（TimeFormat））
func appendTime(b []byte, t time.Time) []byte {
	const days = "SunMonTueWedThuFriSat"
	const months = "JanFebMarAprMayJunJulAugSepOctNovDec"

	t = t.UTC()
	yy, mm, dd := t.Date()
	hh, mn, ss := t.Clock()
	day := days[3*t.Weekday():]
	mon := months[3*(mm-1):]

	return append(b,
		day[0], day[1], day[2], ',', ' ',
		byte('0'+dd/10), byte('0'+dd%10), ' ',
		mon[0], mon[1], mon[2], ' ',
		byte('0'+yy/1000), byte('0'+(yy/100)%10), byte('0'+(yy/10)%10), byte('0'+yy%10), ' ',
		byte('0'+hh/10), byte('0'+hh%10), ':',
		byte('0'+mn/10), byte('0'+mn%10), ':',
		byte('0'+ss/10), byte('0'+ss%10), ' ',
		'G', 'M', 'T')
}

var errTooLarge = errors.New("http: request too large")

// 从连接读取下一个请求。
func (c *conn) readRequest(ctx context.Context) (w *response, err error) {
	if c.hijacked() {
		return nil, ErrHijacked
	}

	var (
		wholeReqDeadline time.Time // 如果没有，则为零
		hdrDeadline      time.Time // 如果没有，则为零
	)
	t0 := time.Now()
	if d := c.server.readHeaderTimeout(); d > 0 {
		hdrDeadline = t0.Add(d)
	}
	if d := c.server.ReadTimeout; d > 0 {
		wholeReqDeadline = t0.Add(d)
	}
	c.rwc.SetReadDeadline(hdrDeadline)
	if d := c.server.WriteTimeout; d > 0 {
		defer func() {
			c.rwc.SetWriteDeadline(time.Now().Add(d))
		}()
	}

	c.r.setReadLimit(c.server.initialReadLimitSize())
	if c.lastMethod == "POST" {
		// RFC 7230第3节旧错误客户端的容差。
		peek, _ := c.bufr.Peek(4) // ReadRequest将在
		c.bufr.Discard(numLeadingCRorLF(peek))
	}
	req, err := readRequest(c.bufr)
	if err != nil {
		if c.r.hitReadLimit() {
			return nil, errTooLarge
		}
		return nil, err
	}

	if !http1ServerSupportsRequest(req) {
		return nil, statusError{StatusHTTPVersionNotSupported, "unsupported protocol version"}
	}

	c.lastMethod = req.Method
	c.r.setInfiniteReadLimit()

	hosts, haveHost := req.Header["Host"]
	isH2Upgrade := req.isH2Upgrade()
	if req.ProtoAtLeast(1, 1) && (!haveHost || len(hosts) == 0) && !isH2Upgrade && req.Method != "CONNECT" {
		return nil, badRequestError("missing required Host header")
	}
	if len(hosts) == 1 && !httpguts.ValidHostHeader(hosts[0]) {
		return nil, badRequestError("malformed Host header")
	}
	for k, vv := range req.Header {
		if !httpguts.ValidHeaderFieldName(k) {
			return nil, badRequestError("invalid header name")
		}
		for _, v := range vv {
			if !httpguts.ValidHeaderFieldValue(v) {
				return nil, badRequestError("invalid header value")
			}
		}
	}
	delete(req.Header, "Host")

	ctx, cancelCtx := context.WithCancel(ctx)
	req.ctx = ctx
	req.RemoteAddr = c.remoteAddr
	req.TLS = c.tlsState
	if body, ok := req.Body.(*body); ok {
		body.doEarlyClose = true
	}

	// 以下出错，如有必要，请调整读取截止日期。
	if !hdrDeadline.Equal(wholeReqDeadline) {
		c.rwc.SetReadDeadline(wholeReqDeadline)
	}

	w = &response{
		conn:          c,
		cancelCtx:     cancelCtx,
		req:           req,
		reqBody:       req.Body,
		handlerHeader: make(Header),
		contentLength: -1,
		closeNotifyCh: make(chan bool, 1),

		// 我们提前填充这些，所以我们不是
		// 从req读取。在他们的处理程序启动
		// 并可能对其进行变异（问题14940）
		wants10KeepAlive: req.wantsHttp10KeepAlive(),
		wantsClose:       req.wantsClose(),
	}
	if isH2Upgrade {
		w.closeAfterReply = true
	}
	w.cw.res = w
	w.w = newBufioWriterSize(&w.cw, bufferBeforeChunkingSize)
	return w, nil
}

// http1ServerSupportsRequest报告Go的HTTP/1。x服务器
// 支持给定的请求。
func http1ServerSupportsRequest(req *Request) bool {
	if req.ProtoMajor == 1 {
		return true
	}
	// 接受“PRI*HTTP/2.0”升级请求，这样处理程序就可以连接自己的HTTP/2升级。
	if req.ProtoMajor == 2 && req.ProtoMinor == 0 &&
		req.Method == "PRI" && req.RequestURI == "*" {
		return true
	}
	// 拒绝HTTP/0。x、 以及所有其他HTTP/2+请求（
	// 无论如何都不是用ASCII编码的）。
	return false
}

func (w *response) Header() Header {
	if w.cw.header == nil && w.wroteHeader && !w.cw.wroteHeader {
		// 在逻辑写入和物理写入之间访问标头意味着我们需要分配
		// 一个克隆来快照逻辑写入状态。
		w.cw.header = w.handlerHeader.Clone()
	}
	w.calledHeader = true
	return w.handlerHeader
}

// maxPostHandlerReadBytes是最大请求数。非
// 由处理程序消耗的正文字节，服务器将从客户端
// 读取该处理程序，以保持连接的活动状态。如果字节数超过
// 则偏执的服务器将发送“Connection:
// close”响应。
// 
// 这个数字大约是典型机器的TCP缓冲区
// 大小。（如果我们在机器上有字节，我们可能会仔细阅读它们）
const maxPostHandlerReadBytes = 256 << 10

func checkWriteHeaderCode(code int) {
	// 问题22880：需要有效的写头状态代码。
	// 目前我们只强制要求它是三位数。
	// 未来我们可能会屏蔽599以上的内容（600及以上未定义
	// https:
	// 我们可能会屏蔽200以下的内容（一旦我们拥有更成熟的1x支持）。
	// 但现在是任意三位数字。
	// 
	// 我们过去经常在网上发送“HTTP/1.1 000 0”作为回应，但这里有
	// 在HTTP/2中，我们实际上无法发送同等的虚假信息，所以我们会一直惊慌失措，帮助人们尽早发现他们的漏洞。（即使我们愿意，也无法从WriteHeader返回错误。）
	if code < 100 || code > 999 {
		panic(fmt.Sprintf("invalid WriteHeader code %v", code))
	}
}

// relevantCaller在调用堆栈中搜索net/http之外的第一个函数。
// 此函数的目的是提供更多有用的错误消息。
func relevantCaller() runtime.Frame {
	pc := make([]uintptr, 16)
	n := runtime.Callers(1, pc)
	frames := runtime.CallersFrames(pc[:n])
	var frame runtime.Frame
	for {
		frame, more := frames.Next()
		if !strings.HasPrefix(frame.Function, "net/http.") {
			return frame
		}
		if !more {
			break
		}
	}
	return frame
}

func (w *response) WriteHeader(code int) {
	if w.conn.hijacked() {
		caller := relevantCaller()
		w.conn.server.logf("http: response.WriteHeader on hijacked connection from %s (%s:%d)", caller.Function, path.Base(caller.File), caller.Line)
		return
	}
	if w.wroteHeader {
		caller := relevantCaller()
		w.conn.server.logf("http: superfluous response.WriteHeader call from %s (%s:%d)", caller.Function, path.Base(caller.File), caller.Line)
		return
	}
	checkWriteHeaderCode(code)
	w.wroteHeader = true
	w.status = code

	if w.calledHeader && w.cw.header == nil {
		w.cw.header = w.handlerHeader.Clone()
	}

	if cl := w.handlerHeader.get("Content-Length"); cl != "" {
		v, err := strconv.ParseInt(cl, 10, 64)
		if err == nil && v >= 0 {
			w.contentLength = v
		} else {
			w.conn.server.logf("http: invalid Content-Length of %q", cl)
			w.handlerHeader.Del("Content-Length")
		}
	}
}

// extraHeader是chunkWriter有时添加的一组头。编剧。
// 此类型用于避免克隆和/或填充
// 响应头映射及其所有1元素片段时的额外分配。
type extraHeader struct {
	contentType      string
	connection       string
	transferEncoding string
	date             []byte // 如果不是零则写入
	contentLength    []byte // 如果不是零则写入
}

// 排序与extraHeader相同。写循环。
var extraHeaderKeys = [][]byte{
	[]byte("Content-Type"),
	[]byte("Connection"),
	[]byte("Transfer-Encoding"),
}

var (
	headerContentLength = []byte("Content-Length: ")
	headerDate          = []byte("Date: ")
)

// Write将h中描述的头写入w。
// 
// 尽管h的大小有点大，但此方法有一个值接收器，因为它阻止分配。转义分析不够聪明，无法实现此函数不会变异h。写入头完成发送给客户端的头并将其写入cw。康涅狄格州。
func (h extraHeader) Write(w *bufio.Writer) {
	if h.date != nil {
		w.Write(headerDate)
		w.Write(h.date)
		w.Write(crlf)
	}
	if h.contentLength != nil {
		w.Write(headerContentLength)
		w.Write(h.contentLength)
		w.Write(crlf)
	}
	for i, v := range []string{h.contentType, h.connection, h.transferEncoding} {
		if v != "" {
			w.Write(extraHeaderKeys[i])
			w.Write(colonSpace)
			w.WriteString(v)
			w.Write(crlf)
		}
	}
}

// 
// p不是由writeHeader编写的，而是将要编写的正文
// 的第一块。如果未显式设置
// 则会嗅探内容类型。如果
// 总体机身尺寸较小，且处理程序已完成
// 运行，则它还用于设置内容长度。
func (cw *chunkWriter) writeHeader(p []byte) {
	if cw.wroteHeader {
		return
	}
	cw.wroteHeader = true

	w := cw.res
	keepAlivesEnabled := w.conn.server.doKeepAlives()
	isHEAD := w.req.Method == "HEAD"

	// 标题写在下面的w.conn.buf中。根据处理程序的
	// 状态，我们是否拥有该映射。如果我们
	// 不拥有它，则会为
	// WriteSubset惰性地创建排除映射以删除头。setHeader结构包含我们需要添加的
	// 头。
	header := cw.header
	owned := header != nil
	if !owned {
		header = w.handlerHeader
	}
	var excludeHeader map[string]bool
	delHeader := func(key string) {
		if owned {
			header.Del(key)
			return
		}
		if _, ok := header[key]; !ok {
			return
		}
		if excludeHeader == nil {
			excludeHeader = make(map[string]bool)
		}
		excludeHeader[key] = true
	}
	var setHeader extraHeader

	// 不要写出假“拖车：foo”键。参见TrailerPrefix。
	trailers := false
	for k := range cw.header {
		if strings.HasPrefix(k, TrailerPrefix) {
			if excludeHeader == nil {
				excludeHeader = make(map[string]bool)
			}
			excludeHeader[k] = true
			trailers = true
		}
	}
	for _, v := range cw.header["Trailer"] {
		trailers = true
		foreachHeaderElement(v, cw.res.declareTrailer)
	}

	te := header.get("Transfer-Encoding")
	hasTE := te != ""

	// 如果处理程序已完成，但从未发送内容长度
	// 响应头，并且这是我们的第一次（也是最后一次）写入，请将
	// 设置为零。这有助于HTTP/1.0客户端保持其
	// /“保持活动”连接的活动状态。
	// 例外：304/204/1xx响应永远不会获得内容长度，如果
	// 这是一个HEAD请求，我们不知道
	// 0个实际字节和0个字节，因为处理程序注意到
	// 是一个HEAD请求，并选择不写入任何内容。因此，对于
	// HEAD，处理程序应该写入内容长度或
	// 写入非零字节。如果它实际上是0字节，并且
	// 处理程序从未查看该请求。方法，我们只是不发送内容长度头。
	// 此外，如果它们设置了传输编码，我们不会发送自动内容长度，因为它们通常不兼容。
	if w.handlerDone.isSet() && !trailers && !hasTE && bodyAllowedForStatus(w.status) && header.get("Content-Length") == "" && (!isHEAD || len(p) > 0) {
		w.contentLength = int64(len(p))
		setHeader.contentLength = strconv.AppendInt(cw.res.clenBuf[:0], int64(len(p)), 10)
	}

	// 如果这是一个带有keep alive的HTTP/1.0请求，并且我们发送了一个返回内容长度的
	// 则我们可以将其作为keep alive响应。。。
	if w.wants10KeepAlive && keepAlivesEnabled {
		sentLength := header.get("Content-Length") != ""
		if sentLength && header.get("Connection") == "keep-alive" {
			w.closeAfterReply = false
		}
	}

	// 检查是否有明确（且有效）的内容长度头。
	hasCL := w.contentLength != -1

	if w.wants10KeepAlive && (isHEAD || hasCL || !bodyAllowedForStatus(w.status)) {
		_, connectionHeaderSet := header["Connection"]
		if !connectionHeaderSet {
			setHeader.connection = "keep-alive"
		}
	} else if !w.req.ProtoAtLeast(1, 1) || w.wantsClose {
		w.closeAfterReply = true
	}

	if header.get("Connection") == "close" || !keepAlivesEnabled {
		w.closeAfterReply = true
	}

	// 如果客户想要100继续，但我们从未将其发送给
	// 他们（或者更严格地说，我们从未读完他们的
	// 请求正文），不要重复使用此连接，因为它现在处于未知状态：我们可能会在
	// 发送此响应，而客户端在超时后正在发送其请求正文
	// 的同时。（一些HTTP客户端发送Expect:
	// 100 continue，但知道一些服务器不支持
	// 它，客户端设置了一个计时器，稍后再发送正文）
	// 如果我们没有看到EOF，我们不能跳过未读的正文
	// 因为我们不知道接下来的字节是
	// 计时器后面的正文还是后续的请求。
	// 见第11549期。
	if ecr, ok := w.req.Body.(*expectContinueReader); ok && !ecr.sawEOF.isSet() {
		w.closeAfterReply = true
	}

	// 根据RFC 2616，如果处理程序还没有这样做，我们应该在
	// 应答之前使用请求正文。但由于
	// DoS原因，我们不想在这里进行无限量的阅读，所以我们只尝试达到一个阈值。
	// TODO（布拉德菲茨）：RFC 2616在哪里这么说？见15527期
	// 关于HTTP/1。x处理程序同时读写，比如
	// HTTP/2处理程序可以完成。也许这个代码应该放宽？
	if w.req.ContentLength != 0 && !w.closeAfterReply {
		var discard, tooBig bool

		switch bdy := w.req.Body.(type) {
		case *expectContinueReader:
			if bdy.resp.wroteContinue {
				discard = true
			}
		case *body:
			bdy.mu.Lock()
			switch {
			case bdy.closed:
				if !bdy.sawEOF {
					// 正文在处理程序中关闭，出现非EOF错误。
					w.closeAfterReply = true
				}
			case bdy.unreadDataSizeLocked() >= maxPostHandlerReadBytes:
				tooBig = true
			default:
				discard = true
			}
			bdy.mu.Unlock()
		default:
			discard = true
		}

		if discard {
			_, err := io.CopyN(io.Discard, w.reqBody, maxPostHandlerReadBytes+1)
			switch err {
			case nil:
				// 一定还有更多的数据。
				tooBig = true
			case ErrBodyReadAfterClose:
				// 身体已被消耗并关闭。
			case io.EOF:
				// 剩下的尸体刚刚被吃掉，关上它。
				err = w.reqBody.Close()
				if err != nil {
					w.closeAfterReply = true
				}
			default:
				// 发生了其他类型的错误，如读取超时或
				// 损坏的分块编码。在任何情况下，导线上剩余的
				// 都不能被解析为另一个HTTP请求。
				w.closeAfterReply = true
			}
		}

		if tooBig {
			w.requestTooLarge()
			delHeader("Connection")
			setHeader.connection = "close"
		}
	}

	code := w.status
	if bodyAllowedForStatus(code) {
		// 如果没有内容类型，则对正文应用嗅探算法。
		_, haveType := header["Content-Type"]

		// 如果内容编码已设置且为非空，
		// 我们不应该嗅探身体。见第31753期。
		ce := header.Get("Content-Encoding")
		hasCE := len(ce) > 0
		if !hasCE && !haveType && !hasTE && len(p) > 0 {
			setHeader.contentType = DetectContentType(p)
		}
	} else {
		for _, k := range suppressedHeaders(code) {
			delHeader(k)
		}
	}

	if !header.has("Date") {
		setHeader.date = appendTime(cw.res.dateBuf[:0], time.Now())
	}

	if hasCL && hasTE && te != "identity" {
		// TODO:如果WriteHeader获取返回参数，则返回一个错误
		// 暂时忽略内容长度。
		w.conn.server.logf("http: WriteHeader called with both Transfer-Encoding of %q and a Content-Length of %d",
			te, w.contentLength)
		delHeader("Content-Length")
		hasCL = false
	}

	if w.req.Method == "HEAD" || !bodyAllowedForStatus(code) || code == StatusNoContent {
		// 响应没有主体。
		delHeader("Transfer-Encoding")
	} else if hasCL {
		// 已提供内容长度，因此不需要进行分块。
		delHeader("Transfer-Encoding")
	} else if w.req.ProtoAtLeast(1, 1) {
		// HTTP/1.1或更高版本：传输编码已设置为标识，未提供
		// 内容长度。在写入
		// 回复后，必须关闭连接，并且不能进行分块。这是服务器发送事件候选建议11，
		// 第8节中推荐的设置。
		if hasTE && te == "identity" {
			cw.chunking = false
			w.closeAfterReply = true
			delHeader("Transfer-Encoding")
		} else {
			// HTTP/1.1或更高版本：使用分块传输编码
			// 避免在EOF关闭连接。
			cw.chunking = true
			setHeader.transferEncoding = "chunked"
			if hasTE && te == "chunked" {
				// 稍后我们将发送分块传输编码头。
				delHeader("Transfer-Encoding")
			}
		}
	} else {
		// HTTP版本<1.1:无法进行分块传输
		// 编码，我们不知道内容长度，所以
		// 通过关闭连接发送EOF信号。
		w.closeAfterReply = true
		delHeader("Transfer-Encoding") // 如果已经设置了
	}

	// 则不能将内容长度与非身份传输编码一起使用。
	if cw.chunking {
		delHeader("Content-Length")
	}
	if !w.req.ProtoAtLeast(1, 0) {
		return
	}

	// 仅当连接头不是成功的
	// 协议切换响应且未启用KeepAlives时，才重写连接头。
	// 参见https:
	delConnectionHeader := w.closeAfterReply &&
		(!keepAlivesEnabled || !hasToken(cw.header.get("Connection"), "close")) &&
		!isProtocolSwitchResponse(w.status, header)
	if delConnectionHeader {
		delHeader("Connection")
		if w.req.ProtoAtLeast(1, 1) {
			setHeader.connection = "close"
		}
	}

	writeStatusLine(w.conn.bufw, w.req.ProtoAtLeast(1, 1), code, w.statusBuf[:])
	cw.header.WriteSubset(w.conn.bufw, excludeHeader)
	setHeader.Write(w.conn.bufw)
	w.conn.bufw.Write(crlf)
}

// foreachHeaderElement根据RFC 7230第7节中的“#规则”构造
// 拆分v，并为每个非空元素调用fn。
func foreachHeaderElement(v string, fn func(string)) {
	v = textproto.TrimString(v)
	if v == "" {
		return
	}
	if !strings.Contains(v, ",") {
		fn(v)
		return
	}
	for _, f := range strings.Split(v, ",") {
		if f = textproto.TrimString(f); f != "" {
			fn(f)
		}
	}
}

// writeStatusLine写入HTTP/1。x状态行（RFC 7230第3.1.2节）
// 至bw。is11是HTTP请求是否为HTTP/1.1。false表示HTTP/1.0。
// 代码是响应状态代码。
// scratch是可选的scratch缓冲区。如果它的容量至少为3，就可以使用它。
func writeStatusLine(bw *bufio.Writer, is11 bool, code int, scratch []byte) {
	if is11 {
		bw.WriteString("HTTP/1.1 ")
	} else {
		bw.WriteString("HTTP/1.0 ")
	}
	if text, ok := statusText[code]; ok {
		bw.Write(strconv.AppendInt(scratch[:0], int64(code), 10))
		bw.WriteByte(' ')
		bw.WriteString(text)
		bw.WriteString("\r\n")
	} else {
		// 不要担心性能
		fmt.Fprintf(bw, "%03d status code %d\r\n", code, code)
	}
}

// bodyAllowed报告是否允许写入此响应类型。
// 在刷新头之前调用此函数是非法的。
func (w *response) bodyAllowed() bool {
	if !w.wroteHeader {
		panic("")
	}
	return bodyAllowedForStatus(w.status)
}

// 写的过程是这样的：
// 
// 处理器启动。尚未发送任何标题。处理程序可以
// 写入头，也可以直接开始写入。发送头前写入
// 发送隐式空的200 OK头。
// 
// 如果处理程序没有预先声明内容长度，我们要么进入分块模式，要么，如果处理程序在分块缓冲区大小之前完成运行，我们计算内容长度并将其发送到头中。
// 
// 同样，如果处理程序没有设置内容类型，我们会从输出的初始块中嗅探该
// 。
// 
// 编剧们像这样连接在一起：
// 
// 1*回复（回复作者）->
// 2。（*回应）。w、 a*bufio。bufferBeforeChunkingSize bytes->
// 3。编剧。Writer（其writeHeader最终确定内容长度/类型）
// 并在需要时写入块头->
// 4。康涅狄格州。写入默认（4kB）字节，写入->
// 5。checkConnErrorWriter{c}，它注意到写入
// 时的任何非零错误，如果是，则用它填充c.werr，否则写入->
// 6。rwc，网络。Conn.
// 
// TODO（bradfitz）：当
// 初始头同时包含内容类型和内容长度时，短路部分缓冲。
// 也在（1）中短路，当标头已发送且未处于
// 分块模式时，如果（2）没有
// 缓冲数据，则直接写入（4）。更一般地说，如果（1）中的写入大小超过某个
// （3）。答案可能主要是让
// 阈值，并且（2）中没有任何内容，则即使在分块模式下，我们也可以从（1）短路到
// bufferBeforeChunkingSize变小，并让bufio的快速路径处理
// 。
func (w *response) Write(data []byte) (n int, err error) {
	return w.write(len(data), data, "")
}

func (w *response) WriteString(data string) (n int, err error) {
	return w.write(len(data), nil, data)
}

// DATA或DATA都不是零。
func (w *response) write(lenData int, dataB []byte, dataS string) (n int, err error) {
	if w.conn.hijacked() {
		if lenData > 0 {
			caller := relevantCaller()
			w.conn.server.logf("http: response.Write on hijacked connection from %s (%s:%d)", caller.Function, path.Base(caller.File), caller.Line)
		}
		return 0, ErrHijacked
	}

	if w.canWriteContinue.isSet() {
		// Body reader想继续写100，但还没有。
		// 告诉它不要这样做。必须在持有锁
		// 的同时进行存储，因为锁确保此时没有活动的写入
		// 操作。
		w.writeContinueMu.Lock()
		w.canWriteContinue.setFalse()
		w.writeContinueMu.Unlock()
	}

	if !w.wroteHeader {
		w.WriteHeader(StatusOK)
	}
	if lenData == 0 {
		return 0, nil
	}
	if !w.bodyAllowed() {
		return 0, ErrBodyNotAllowed
	}

	w.written += int64(lenData) // 忽略错误，因为错误模糊
	if w.contentLength != -1 && w.written > w.contentLength {
		return 0, ErrContentLength
	}
	if dataB != nil {
		return w.w.Write(dataB)
	} else {
		return w.w.WriteString(dataS)
	}
}

func (w *response) finishRequest() {
	w.handlerDone.setTrue()

	if !w.wroteHeader {
		w.WriteHeader(StatusOK)
	}

	w.w.Flush()
	putBufioWriter(w.w)
	w.cw.close()
	w.conn.bufw.Flush()

	w.conn.r.abortPendingRead()

	// 关闭主体（不管w.closeAfterReply），这样我们就可以
	// 重新使用它的bufio。读者请稍后安全阅读。
	w.reqBody.Close()

	if w.req.MultipartForm != nil {
		w.req.MultipartForm.RemoveAll()
	}
}

// shouldReuseConnection报告底层TCP连接是否可以重用。
// 只能在处理程序执行完毕后调用它。
func (w *response) shouldReuseConnection() bool {
	if w.closeAfterReply {
		// 执行
		// 处理程序时设置的请求或内容表明，我们不应重复使用此
		// 连接。
		return false
	}

	if w.req.Method != "HEAD" && w.contentLength != -1 && w.bodyAllowed() && w.contentLength != w.written {
		// 写得不够。避免失去同步。
		return false
	}

	// 在请求过程中写入基础连接
	// 时出错，因此不要重新使用此连接。
	if w.conn.werr != nil {
		return false
	}

	if w.closedRequestBodyEarly() {
		return false
	}

	return true
}

func (w *response) closedRequestBodyEarly() bool {
	body, ok := w.req.Body.(*body)
	return ok && body.didEarlyClose()
}

func (w *response) Flush() {
	if !w.wroteHeader {
		w.WriteHeader(StatusOK)
	}
	w.w.Flush()
	w.cw.flush()
}

func (c *conn) finalFlush() {
	if c.bufr != nil {
		// 窃取bufio。读卡器（~4KB内存）及其关联的
		// 读卡器，用于将来的连接。
		putBufioReader(c.bufr)
		c.bufr = nil
	}

	if c.bufw != nil {
		c.bufw.Flush()
		// 偷布菲奥。Writer（~4KB内存）及其关联的
		// 用于未来连接的Writer。
		putBufioWriter(c.bufw)
		c.bufw = nil
	}
}

// 关闭连接。
func (c *conn) close() {
	c.finalFlush()
	c.rwc.Close()
}

// rstAvoidanceDelay是关闭整个套接字之前，我们在关闭TCP连接的写入端后睡眠的时间量。
// 通过睡眠，我们增加了客户看到我们的FIN 
// 并在处理后续RST 
// 之前处理其最终数据的机会，从而避免客户关闭与已知未读数据的连接。
// 这种RST似乎主要发生在BSD系统上。（还有窗户？）
// 这个超时有点随意（~在地球上的延迟）。
const rstAvoidanceDelay = 500 * time.Millisecond

type closeWriter interface {
	CloseWrite() error
}

var _ closeWriter = (*net.TCPConn)(nil)

// closeWrite刷新所有未完成的数据，并发送FIN数据包（如果
// 客户端通过TCP连接），表示我们完成了。然后我们暂停一会儿，希望客户在任何后续RST之前处理它。
// 参见https:
func (c *conn) closeWriteAndWait() {
	c.finalFlush()
	if tcp, ok := c.rwc.(closeWriter); ok {
		tcp.CloseWrite()
	}
	time.Sleep(rstAvoidanceDelay)
}

// validNextProto报告proto是否为有效的ALPN协议名称。
// 除了空字符串和内置协议类型
// 之外，所有内容都是有效的，因此这些内容不能被替代实现覆盖。
func validNextProto(proto string) bool {
	switch proto {
	case "", "http/1.1", "http/1.0":
		return false
	}
	return true
}

const (
	runHooks  = true
	skipHooks = false
)

func (c *conn) setState(nc net.Conn, state ConnState, runHook bool) {
	srv := c.server
	switch state {
	case StateNew:
		srv.trackConn(c, true)
	case StateHijacked, StateClosed:
		srv.trackConn(c, false)
	}
	if state > 0xff || state < 0 {
		panic("internal error")
	}
	packedState := uint64(time.Now().Unix()<<8) | uint64(state)
	atomic.StoreUint64(&c.curState.atomic, packedState)
	if !runHook {
		return
	}
	if hook := srv.ConnState; hook != nil {
		hook(nc, state)
	}
}

func (c *conn) getState() (state ConnState, unixSec int64) {
	packedState := atomic.LoadUint64(&c.curState.atomic)
	return ConnState(packedState & 0xff), int64(packedState >> 8)
}

// badRequestError是一个文本字符串（在服务器中以HTML、
// unscaped的形式使用），用于告诉用户其请求错误的原因。它应该是没有用户信息或其他嵌入错误的纯文本。
func badRequestError(e string) error { return statusError{StatusBadRequest, e} }

// statusError是一种用于以HTTP状态响应请求的错误。
// 文本应为纯文本，无用户信息或其他嵌入错误。
type statusError struct {
	code int
	text string
}

func (e statusError) Error() string { return StatusText(e.code) + ": " + e.text }

// ErrAbortHandler是一个用于中止处理程序的哨兵恐慌值。
// 来自ServeHTTP的任何恐慌都会中止对客户端的响应，而
// 与ErrAbortHandler的恐慌也会抑制堆栈的日志记录
// 对服务器错误日志的跟踪。
var ErrAbortHandler = errors.New("net/http: abort Handler")

// ISCOMMONTEADERROR报告错误是否为常见错误
// 当
// 客户端离开或以某种方式读取失败时，从网络读取请求时遇到的错误。这用于
// 确定哪些日志值得记录。
func isCommonNetReadError(err error) bool {
	if err == io.EOF {
		return true
	}
	if neterr, ok := err.(net.Error); ok && neterr.Timeout() {
		return true
	}
	if oe, ok := err.(*net.OpError); ok && oe.Op == "read" {
		return true
	}
	return false
}

// 为新连接提供服务。
func (c *conn) serve(ctx context.Context) {
	c.remoteAddr = c.rwc.RemoteAddr().String()
	ctx = context.WithValue(ctx, LocalAddrContextKey, c.rwc.LocalAddr())
	var inFlightResponse *response
	defer func() {
		if err := recover(); err != nil && err != ErrAbortHandler {
			const size = 64 << 10
			buf := make([]byte, size)
			buf = buf[:runtime.Stack(buf, false)]
			c.server.logf("http: panic serving %v: %v\n%s", c.remoteAddr, err, buf)
		}
		if inFlightResponse != nil {
			inFlightResponse.cancelCtx()
		}
		if !c.hijacked() {
			if inFlightResponse != nil {
				inFlightResponse.conn.r.abortPendingRead()
				inFlightResponse.reqBody.Close()
			}
			c.close()
			c.setState(c.rwc, StateClosed, runHooks)
		}
	}()

	if tlsConn, ok := c.rwc.(*tls.Conn); ok {
		tlsTO := c.server.tlsHandshakeTimeout()
		if tlsTO > 0 {
			dl := time.Now().Add(tlsTO)
			c.rwc.SetReadDeadline(dl)
			c.rwc.SetWriteDeadline(dl)
		}
		if err := tlsConn.HandshakeContext(ctx); err != nil {
			// 如果由于客户端不讲
			// TLS而导致握手失败，则假设他们讲的是纯文本HTTP，并在TLS连接的基础网络上编写
			// 400响应。Conn.
			if re, ok := err.(tls.RecordHeaderError); ok && re.Conn != nil && tlsRecordHeaderLooksLikeHTTP(re.RecordHeader) {
				io.WriteString(re.Conn, "HTTP/1.0 400 Bad Request\r\n\r\nClient sent an HTTP request to an HTTPS server.\n")
				re.Conn.Close()
				return
			}
			c.server.logf("http: TLS handshake error from %s: %v", c.rwc.RemoteAddr(), err)
			return
		}
		// 恢复Conn级别的截止日期。wen jian defg
		if tlsTO > 0 {
			c.rwc.SetReadDeadline(time.Time{})
			c.rwc.SetWriteDeadline(time.Time{})
		}
		c.tlsState = new(tls.ConnectionState)
		*c.tlsState = tlsConn.ConnectionState()
		if proto := c.tlsState.NegotiatedProtocol; validNextProto(proto) {
			if fn := c.server.TLSNextProto[proto]; fn != nil {
				h := initALPNRequest{ctx, tlsConn, serverHandler{c.server}}
				c.setState(c.rwc, StateActive, skipHooks)
				fn(c.server, tlsConn, h)
			}
			return
		}
	}

	// HTTP/1。从现在开始。

	ctx, cancelCtx := context.WithCancel(ctx)
	c.cancelCtx = cancelCtx
	defer cancelCtx()

	c.r = &connReader{conn: c}
	c.bufr = newBufioReader(c.r)
	c.bufw = newBufioWriterSize(checkConnErrorWriter{c}, 4<<10)

	for {
		w, err := c.readRequest(ctx)
		if c.r.remain != c.server.initialReadLimitSize() {
			// 如果我们从线路上读取任何字节，我们就处于活动状态。
			c.setState(c.rwc, StateActive, runHooks)
		}
		if err != nil {
			const errorHeaders = "\r\nContent-Type: text/plain; charset=utf-8\r\nConnection: close\r\n\r\n"

			switch {
			case err == errTooLarge:
				// 他们的HTTP客户端可能是也可能不是
				// 如果我们是
				// 响应他们并挂断
				// 而他们仍在编写
				// 请求时，可以阅读此内容。未定义的行为。
				const publicErr = "431 Request Header Fields Too Large"
				fmt.Fprintf(c.rwc, "HTTP/1.1 "+publicErr+errorHeaders+publicErr)
				c.closeWriteAndWait()
				return

			case isUnsupportedTEError(err):
				// 根据RFC 7230第3.3.1节进行响应，该节规定，
				// 接收带有
				// 传输编码的请求消息的服务器应使用501（未实现）进行响应。
				code := StatusNotImplemented

				// 我们无意回显传输编码的值
				// 以降低攻击者跨端脚本编写的风险。
				fmt.Fprintf(c.rwc, "HTTP/1.1 %d %s%sUnsupported transfer encoding", code, StatusText(code), errorHeaders)
				return

			case isCommonNetReadError(err):
				return // 不要回复

			default:
				if v, ok := err.(statusError); ok {
					fmt.Fprintf(c.rwc, "HTTP/1.1 %d %s: %s%s%d %s: %s", v.code, StatusText(v.code), v.text, errorHeaders, v.code, StatusText(v.code), v.text)
					return
				}
				publicErr := "400 Bad Request"
				fmt.Fprintf(c.rwc, "HTTP/1.1 "+publicErr+errorHeaders+publicErr)
				return
			}
		}

		// 期待100继续支持
		req := w.req
		if req.expectsContinue() {
			if req.ProtoAtLeast(1, 1) && req.ContentLength != 0 {
				// 用一个在连接上回复的读体器包装
				req.Body = &expectContinueReader{readCloser: req.Body, resp: w}
				w.canWriteContinue.setTrue()
			}
		} else if req.Header.get("Expect") != "" {
			w.sendExpectationFailed()
			return
		}

		c.curReq.Store(w)

		if requestBodyRemains(req.Body) {
			registerOnHitEOF(req.Body, w.conn.r.startBackgroundRead)
		} else {
			w.conn.r.startBackgroundRead()
		}

		// HTTP不能同时有多个活动请求。[*]
		// 在服务器回复此请求之前，它无法读取另一个请求，
		// 因此我们不妨在这个goroutine中运行处理程序。
		// /[*]严格来说不是真的：HTTP管道。我们可以让他们并行处理
		// 即使他们的响应需要序列化。
		// 但我们不打算实现HTTP管道，因为它从未在野外部署过，答案是HTTP/2。
		inFlightResponse = w
		serverHandler{c.server}.ServeHTTP(w, w.req)
		inFlightResponse = nil
		w.cancelCtx()
		if c.hijacked() {
			return
		}
		w.finishRequest()
		if !w.shouldReuseConnection() {
			if w.requestBodyLimitHit || w.closedRequestBodyEarly() {
				c.closeWriteAndWait()
			}
			return
		}
		c.setState(c.rwc, StateIdle, runHooks)
		c.curReq.Store((*response)(nil))

		if !w.conn.server.doKeepAlives() {
			// 我们处于关机模式。我们可能已经回复了
			// 给没有“连接：关闭”和
			// 的用户，他们可能认为他们可以发送另一个
			// 请求，但这就是HTTP/1.1的生活。
			return
		}

		if d := c.server.idleTimeout(); d != 0 {
			c.rwc.SetReadDeadline(time.Now().Add(d))
			if _, err := c.bufr.Peek(4); err != nil {
				return
			}
		}
		c.rwc.SetReadDeadline(time.Time{})
	}
}

func (w *response) sendExpectationFailed() {
	// TODO（bradfitz）：让ServeHTTP处理程序处理
	// 具有非标准期望的请求？似乎
	// 充其量只是理论上的，无论如何都不适合
	// 当前的ServeHTTP模型。我们需要把ResponseWriter设置为可选的ExpectReplier接口。
	// 
	// 现在我们只需遵守RFC 7231 5.1.1，其中说
	// “如果服务器接收到除
	// 100 continue之外的预期字段值，则可能会响应417（预期
	// 失败）状态代码，以指示无法满足意外的
	// 预期。”
	w.Header().Set("Connection", "close")
	w.WriteHeader(StatusExpectationFailed)
	w.finishRequest()
}

// 劫机者实施了劫机者。劫持方法。我们的回应既是回应作者
// 又是劫机者。
func (w *response) Hijack() (rwc net.Conn, buf *bufio.ReadWriter, err error) {
	if w.handlerDone.isSet() {
		panic("net/http: Hijack called after ServeHTTP finished")
	}
	if w.wroteHeader {
		w.cw.flush()
	}

	c := w.conn
	c.mu.Lock()
	defer c.mu.Unlock()

	// 释放写入区块编写器的bufioWriter，它不是
	// 在连接被劫持后使用。
	rwc, buf, err = c.hijackLocked()
	if err == nil {
		putBufioWriter(w.w)
		w.w = nil
	}
	return rwc, buf, err
}

func (w *response) CloseNotify() <-chan bool {
	if w.handlerDone.isSet() {
		panic("net/http: CloseNotify called after ServeHTTP finished")
	}
	return w.closeNotifyCh
}

func registerOnHitEOF(rc io.ReadCloser, fn func()) {
	switch v := rc.(type) {
	case *expectContinueReader:
		registerOnHitEOF(v.readCloser, fn)
	case *body:
		v.registerOnHitEOF(fn)
	default:
		panic("unexpected type " + fmt.Sprintf("%T", rc))
	}
}

// RequestBodyResistes报告未来在rc上读取
// 的调用是否会产生更多数据。
func requestBodyRemains(rc io.ReadCloser) bool {
	if rc == NoBody {
		return false
	}
	switch v := rc.(type) {
	case *expectContinueReader:
		return requestBodyRemains(v.readCloser)
	case *body:
		return v.bodyRemains()
	default:
		panic("unexpected type " + fmt.Sprintf("%T", rc))
	}
}

// HandlerFunc类型是允许使用
// 作为HTTP处理程序的普通函数。如果f是一个带有适当签名的函数
// 那么HandlerFunc（f）是一个调用f的
// 处理程序。
type HandlerFunc func(ResponseWriter, *Request)

// ServeHTTP调用f（w，r）。
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
	f(w, r)
}

// 助手处理程序

// 错误使用指定的错误消息和HTTP代码回复请求。
// 否则不会结束请求；调用者应确保不对w进行进一步的
// 写入操作。
// 错误消息应为纯文本。
func Error(w ResponseWriter, error string, code int) {
	w.Header().Set("Content-Type", "text/plain; charset=utf-8")
	w.Header().Set("X-Content-Type-Options", "nosniff")
	w.WriteHeader(code)
	fmt.Fprintln(w, error)
}

// NotFound回复请求时出现HTTP 404 not found错误。
func NotFound(w ResponseWriter, r *Request) { Error(w, "404 page not found", StatusNotFound) }

// NotFoundHandler返回一个简单的请求处理程序
// 该处理程序用“404页面未找到”回复每个请求。
func NotFoundHandler() Handler { return HandlerFunc(NotFound) }

// StripPrefix返回一个处理程序，该处理程序通过从请求URL的路径（以及RawPath，如果已设置）中删除给定的前缀，并调用
// h处理程序来为HTTP请求提供服务。StripPrefix通过回复HTTP 404 not found错误来处理对路径的请求，该路径不以前缀
// 开头。前缀必须
// 完全匹配：如果请求中的前缀包含转义字符
// 则回复也是HTTP 404 not found错误。
func StripPrefix(prefix string, h Handler) Handler {
	if prefix == "" {
		return h
	}
	return HandlerFunc(func(w ResponseWriter, r *Request) {
		p := strings.TrimPrefix(r.URL.Path, prefix)
		rp := strings.TrimPrefix(r.URL.RawPath, prefix)
		if len(p) < len(r.URL.Path) && (r.URL.RawPath == "" || len(rp) < len(r.URL.RawPath)) {
			r2 := new(Request)
			*r2 = *r
			r2.URL = new(url.URL)
			*r2.URL = *r.URL
			r2.URL.Path = p
			r2.URL.RawPath = rp
			h.ServeHTTP(w, r2)
		} else {
			NotFound(w, r)
		}
	})
}

// 用重定向到url的方式重定向对请求的回复，
// 这可能是相对于请求路径的路径。
// 
// 提供的代码应在3xx范围内，通常为
// 状态永久移动、状态找到或状态查看其他。
// 
// 如果尚未设置内容类型头，重定向会将其设置为“text/html；charset=utf-8”，并编写一个小的html正文。
// 将内容类型头设置为任何值，包括nil，
// 将禁用该行为。
func Redirect(w ResponseWriter, r *Request, url string, code int) {
	if u, err := urlpkg.Parse(url); err == nil {
		// 如果url是相对的，则通过
		// 结合请求路径将其路径设置为绝对路径。
		// 客户可能会为我们做这件事，但自己做更可靠。
		// 参见RFC 7231第7.1.2节
		if u.Scheme == "" && u.Host == "" {
			oldpath := r.URL.Path
			if oldpath == "" { // 不应发生，但是避免崩溃，如果它真的这样做了
				oldpath = "/"
			}

			// 没有领先的http:
			if url == "" || url[0] != '/' {
				// 使相对路径绝对
				olddir, _ := path.Split(oldpath)
				url = olddir + url
			}

			var query string
			if i := strings.Index(url, "?"); i != -1 {
				url, query = url[:i], url[i:]
			}

			// 清理但保留尾部斜杠
			trailing := strings.HasSuffix(url, "/")
			url = path.Clean(url)
			if trailing && !strings.HasSuffix(url, "/") {
				url += "/"
			}
			url += query
		}
	}

	h := w.Header()

	// RFC 7231注意到，
	// 响应中通常包含一个短的HTML正文，因为较老的用户代理可能不理解301/307。
	// 仅当请求没有内容类型头时才执行此操作。
	_, hadCT := h["Content-Type"]

	h.Set("Location", hexEscapeNonASCII(url))
	if !hadCT && (r.Method == "GET" || r.Method == "HEAD") {
		h.Set("Content-Type", "text/html; charset=utf-8")
	}
	w.WriteHeader(code)

	// 不应将身体发送给职位或负责人；那会让你失望。
	if !hadCT && r.Method == "GET" {
		body := "<a href=\"" + htmlEscape(url) + "\">" + statusText[code] + "</a>.\n"
		fmt.Fprintln(w, body)
	}
}

var htmlReplacer = strings.NewReplacer(
	"&", "&amp;",
	"<", "&lt;",
	">", "&gt;",
	// /“&#34；”比“短”。
	`"`, "&#34;",
	// /“&#39；”短于“&apos；”而apos直到HTML5才出现在HTML中。
	"'", "&#39;",
)

func htmlEscape(s string) string {
	return htmlReplacer.Replace(s)
}

// 重定向到固定URL 
type redirectHandler struct {
	url  string
	code int
}

func (rh *redirectHandler) ServeHTTP(w ResponseWriter, r *Request) {
	Redirect(w, r, rh.url, rh.code)
}

// 重定向处理程序返回一个请求处理程序，该处理程序使用给定的
// 状态代码将收到的每个请求重定向到给定的URL。
// 
// 提供的代码应在3xx范围内，通常为
// 状态永久移动、状态找到或状态查看其他。
func RedirectHandler(url string, code int) Handler {
	return &redirectHandler{url, code}
}

// ServeMux是一个HTTP请求多路复用器。
// 它将每个传入请求的URL与已注册的
// 模式列表相匹配，并调用与URL最匹配的模式的处理程序。
// 
// 模式名称固定的有根路径，如“/favicon.ico”，
// 或有根子树，如“/images/”（注意尾随的斜杠）。
// 较长的模式优先于较短的模式，因此
// 如果有为“/images/”和“/images/thumbnails/”注册的处理程序，后一个处理程序将是
// 调用以“/images/thumbnails/”开头的路径，而
// 前者将接收对
// /“/images/”子树中任何其他路径的请求。
// 
// 注意，由于以斜杠结尾的模式命名有根子树，因此
// 模式“/”匹配所有未被其他注册的
// 模式匹配的路径，而不仅仅是路径=“/”的URL。
// 
// 如果已注册子树，并收到一个命名
// 子树根的请求，但不带尾随斜杠，ServeMux会将该
// 请求重定向到子树根（添加尾随斜杠）。此行为可以被覆盖，只需对路径进行单独的注册，而不必使用尾随斜杠。例如，注册“/images/”会导致ServeMux 
// 将对“/images”的请求重定向到“/images/”，除非“/images”已单独注册
// 文件。
// 
// 模式可以选择以主机名开头，将匹配限制为仅该主机上的
// URL。特定于主机的模式优先于
// 常规模式，因此处理程序可能会注册两种模式
// “/codesearch”和“codesearch.google.com/”，而不会同时接收
// 请求”http:
// 
// ServeMux还负责清理URL请求路径和主机
// 标头，剥离端口号，并将任何包含.或
// ……元素或重复斜杠的请求重定向到等效的、更干净的URL。
type ServeMux struct {
	mu    sync.RWMutex
	m     map[string]muxEntry
	es    []muxEntry // 按从最长到最短排序的条目片段。
	hosts bool       // 任何模式都包含主机名
}

type muxEntry struct {
	h       Handler
	pattern string
}

// NewServeMux分配并返回一个新的ServeMux。
func NewServeMux() *ServeMux { return new(ServeMux) }

// DefaultServeMux是Serve使用的默认ServeMux。
var DefaultServeMux = &defaultServeMux

var defaultServeMux ServeMux

// cleanPath返回p的规范路径，消除。和元素。
func cleanPath(p string) string {
	if p == "" {
		return "/"
	}
	if p[0] != '/' {
		p = "/" + p
	}
	np := path.Clean(p)
	// 路径。清除除根以外的尾部斜线；
	// 如有必要，将尾部斜杠放回原处。
	if p[len(p)-1] == '/' && np != "/" {
		// p是我们想要的字符串的常见情况的快速路径：
		if len(p) == len(np)+1 && strings.HasPrefix(p, np) {
			np = p
		} else {
			np += "/"
		}
	}
	return np
}

// stripHostPort返回h，不带任何尾随“：<port>”。
func stripHostPort(h string) string {
	// 如果主机上没有端口，则返回unchanged 
	if !strings.Contains(h, ":") {
		return h
	}
	host, _, err := net.SplitHostPort(h)
	if err != nil {
		return h // 如果出现错误，则返回unchanged 
	}
	return host
}

// 在给定路径字符串的处理程序映射上查找处理程序。
// 最具体（最长）的模式获胜。
func (mux *ServeMux) match(path string) (h Handler, pattern string) {
	// 首先检查是否完全匹配。
	v, ok := mux.m[path]
	if ok {
		return v.h, v.pattern
	}

	// 检查最长有效匹配。多路复用器。es包含所有以从最长到最短的顺序结束的模式。
	for _, e := range mux.es {
		if strings.HasPrefix(path, e.pattern) {
			return e.h, e.pattern
		}
	}
	return nil, ""
}

// redirectToPathSlash确定给定路径是否需要附加“/”。
// 当路径+“/”的处理程序已经注册，但
// 不是路径本身时，就会发生这种情况。如果路径需要附加到，它会创建一个新的
// URL，将路径设置为u.path+“/”并返回true以指示是否添加。
func (mux *ServeMux) redirectToPathSlash(host, path string, u *url.URL) (*url.URL, bool) {
	mux.mu.RLock()
	shouldRedirect := mux.shouldRedirectRLocked(host, path)
	mux.mu.RUnlock()
	if !shouldRedirect {
		return u, false
	}
	path = path + "/"
	u = &url.URL{Path: path, RawQuery: u.RawQuery}
	return u, true
}

// shouldRedirecterLocked报告是否应将给定的路径和主机重定向到
// path+“/”。如果为path+“/”注册了一个处理程序，但
// 不是path，则应该发生这种情况——请参阅ServeMax上的注释。
func (mux *ServeMux) shouldRedirectRLocked(host, path string) bool {
	p := []string{path, host + path}

	for _, c := range p {
		if _, exist := mux.m[c]; exist {
			return false
		}
	}

	n := len(path)
	if n == 0 {
		return false
	}
	for _, c := range p {
		if _, exist := mux.m[c+"/"]; exist {
			return path[n-1] != '/'
		}
	}

	return false
}

// Handler返回用于给定请求的处理程序，
// consulting r.Method、r.Host和r.URL。路径它总是返回
// 一个非零处理程序。如果路径不是其规范形式，则
// 处理程序将是一个内部生成的处理程序，它会将
// 重定向到规范路径。如果主机包含端口，则在匹配处理程序时将忽略该端口。
// 
// 连接请求使用的路径和主机不变。
// 
// 处理程序还返回与
// 请求匹配的注册模式，或者在内部生成重定向的情况下，返回在重定向后将匹配的模式。
// 
// 如果没有应用于请求的已注册处理程序，
// 处理程序将返回一个“未找到页面”处理程序和一个空模式。
func (mux *ServeMux) Handler(r *Request) (h Handler, pattern string) {

	// 未规范化连接请求。
	if r.Method == "CONNECT" {
		// If r.URL。路径为/tree且其处理程序未注册，/tree->/tree/redirect适用于连接请求，但路径规范化不适用。
		if u, ok := mux.redirectToPathSlash(r.URL.Host, r.URL.Path, r.URL); ok {
			return RedirectHandler(u.String(), StatusMovedPermanently), u.Path
		}

		return mux.handler(r.Host, r.URL.Path)
	}

	// 所有其他请求在传递到mux之前都会剥离任何端口并清理路径。处理程序。
	host := stripHostPort(r.Host)
	path := cleanPath(r.URL.Path)

	// 如果给定路径为/tree，且其处理程序未注册，则
	// 重定向为/tree/。
	if u, ok := mux.redirectToPathSlash(host, path, r.URL); ok {
		return RedirectHandler(u.String(), StatusMovedPermanently), u.Path
	}

	if path != r.URL.Path {
		_, pattern = mux.handler(host, path)
		u := &url.URL{Path: path, RawQuery: r.URL.RawQuery}
		return RedirectHandler(u.String(), StatusMovedPermanently), pattern
	}

	return mux.handler(host, r.URL.Path)
}

// handler是handler的主要实现。
// 已知路径为规范形式，但CONNECT方法除外。
func (mux *ServeMux) handler(host, path string) (h Handler, pattern string) {
	mux.mu.RLock()
	defer mux.mu.RUnlock()

	// 特定于主机的模式优先于通用模式
	if mux.hosts {
		h, pattern = mux.match(host + path)
	}
	if h == nil {
		h, pattern = mux.match(path)
	}
	if h == nil {
		h, pattern = NotFoundHandler(), ""
	}
	return
}

// ServeHTTP将请求分派给其
// 模式与请求URL最匹配的处理程序。
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
	if r.RequestURI == "*" {
		if r.ProtoAtLeast(1, 1) {
			w.Header().Set("Connection", "close")
		}
		w.WriteHeader(StatusBadRequest)
		return
	}
	h, _ := mux.Handler(r)
	h.ServeHTTP(w, r)
}

// Handle为给定模式注册处理程序。
// 如果模式已经存在处理程序，请处理恐慌。
func (mux *ServeMux) Handle(pattern string, handler Handler) {
	mux.mu.Lock()
	defer mux.mu.Unlock()

	if pattern == "" {
		panic("http: invalid pattern")
	}
	if handler == nil {
		panic("http: nil handler")
	}
	if _, exist := mux.m[pattern]; exist {
		panic("http: multiple registrations for " + pattern)
	}

	if mux.m == nil {
		mux.m = make(map[string]muxEntry)
	}
	e := muxEntry{h: handler, pattern: pattern}
	mux.m[pattern] = e
	if pattern[len(pattern)-1] == '/' {
		mux.es = appendSorted(mux.es, e)
	}

	if pattern[0] != '/' {
		mux.hosts = true
	}
}

func appendSorted(es []muxEntry, e muxEntry) []muxEntry {
	n := len(es)
	i := sort.Search(n, func(i int) bool {
		return len(es[i].pattern) < len(e.pattern)
	})
	if i == n {
		return append(es, e)
	}
	// 我们现在知道，我指的是我们想要插入的位置
	es = append(es, muxEntry{}) // 试着在适当的位置增加切片，任何条目都可以。
	copy(es[i+1:], es[i:])      // 向下移动较短的条目
	es[i] = e
	return es
}

// HandleFunc为给定模式注册处理函数。
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
	if handler == nil {
		panic("http: nil handler")
	}
	mux.Handle(pattern, HandlerFunc(handler))
}

// Handle在DefaultServeMux中注册给定模式
// 的处理程序。
// ServeMux的文档解释了模式是如何匹配的。
func Handle(pattern string, handler Handler) { DefaultServeMux.Handle(pattern, handler) }

// HandleFunc在DefaultServeMux中注册给定模式
// 的处理函数。
// ServeMux的文档解释了模式是如何匹配的。
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
	DefaultServeMux.HandleFunc(pattern, handler)
}

// Serve在侦听器l上接受传入的HTTP连接，
// 为每个连接创建一个新的服务goroutine。服务goroutines 
// 读取请求，然后调用处理程序回复请求。
// 
// 处理程序通常为nil，在这种情况下使用DefaultServeMux。
// 
// HTTP/2支持仅在侦听器返回*tls时启用。Conn 
// 连接，它们在TLS 
// 配置中配置为“h2”。下一本。
// 
// Serve始终返回非零错误。
func Serve(l net.Listener, handler Handler) error {
	srv := &Server{Handler: handler}
	return srv.Serve(l)
}

// ServeTLS在侦听器l上接受传入的HTTPS连接，
// 为每个连接创建一个新的服务goroutine。服务goroutines 
// 读取请求，然后调用处理程序回复请求。
// 
// 处理程序通常为nil，在这种情况下使用DefaultServeMux。
// 
// 此外，必须为服务器提供包含证书和匹配私钥
// 的文件。如果证书由
// 证书颁发机构签名，则certFile应该是服务器证书、任何中间证书和CA证书的串联
// 文件。
// 
// ServeTLS始终返回非零错误。
func ServeTLS(l net.Listener, handler Handler, certFile, keyFile string) error {
	srv := &Server{Handler: handler}
	return srv.ServeTLS(l, certFile, keyFile)
}

// 服务器定义运行HTTP服务器的参数。
// 服务器的零值是有效的配置。
type Server struct {
	// Addr可选地指定服务器要侦听的TCP地址，
	// 格式为“主机：端口”。如果为空，则使用“：http”（端口80）。
	// 服务名称在RFC 6335中定义，并由IANA分配。
	// 见网络。拨打电话了解地址格式的详细信息。
	Addr string

	Handler Handler // 要调用的处理程序，http。DefaultServeUx if nil 

	// TLSConfig可选地提供一个TLS配置，供ServeTLS和ListendServetls使用。请注意，该值是由ServeTLS和ListendServetls克隆的
	// 因此不能使用
	// 之类的方法修改配置。配置。设置SessionTicketKeys。要使用
	// SetSessionTicketKeys，请使用服务器。与TLS监听器
	// 一起使用。
	TLSConfig *tls.Config

	// ReadTimeout是读取整个
	// 请求（包括正文）的最长持续时间。零或负值表示
	// 将不会有超时。
	// 
	// 因为ReadTimeout不允许处理程序对每个请求进行处理
	// 决定每个请求主体的可接受截止日期或
	// 上载速率，大多数用户更喜欢使用
	// ReadHeaderTimeout。两者都可以使用。
	ReadTimeout time.Duration

	// ReadHeaderTimeout是读取
	// 请求头所允许的时间量。读取头之后，连接的读取截止时间被重置
	// 处理程序可以决定哪个
	// 对于主体来说太慢。如果ReadHeaderTimeout 
	// 为零，则使用ReadTimeout的值。如果两者都是
	// 零，则没有超时。
	ReadHeaderTimeout time.Duration

	// WriteTimeout是超时前的最长持续时间
	// 写入响应。每当读取新的
	// 请求的头时，它就会重置。与ReadTimeout一样，它不允许处理程序根据每个请求做出决定。
	// 零或负值表示没有超时。
	WriteTimeout time.Duration

	// IdleTimeout是启用保留生命时等待
	// 下一个请求的最长时间。如果IdleTimeout 
	// 为零，则使用ReadTimeout的值。如果两者都是
	// 零，则没有超时。
	IdleTimeout time.Duration

	// MaxHeaderBytes控制
	// 服务器在解析请求头的密钥和
	// 值（包括请求行）时读取的最大字节数。它不限制请求正文的
	// 大小。
	// 如果为零，则使用DefaultMaxHeaderBytes。
	MaxHeaderBytes int

	// TLSNextProto可选地指定一个函数来接管
	// 发生ALPN 
	// 协议升级时提供的TLS连接的所有权。映射密钥是协议
	// 名称协商。Handler参数应用于处理HTTP请求，并将初始化请求的TLS 
	// 和RemoteAddr（如果尚未设置）。连接为
	// 函数返回时自动关闭。
	// 如果TLSNextProto不是nil，则不会自动启用HTTP/2支持。
	TLSNextProto map[string]func(*Server, *tls.Conn, Handler)

	// ConnState指定一个可选的回调函数，当客户端连接更改状态时调用该函数。有关详细信息，请参阅
	// ConnState类型和关联的常量。
	ConnState func(net.Conn, ConnState)

	// ErrorLog指定一个可选的记录器，用于接收错误的
	// 连接、来自处理程序的意外行为，以及
	// 基础文件系统错误。
	// 如果为零，则通过日志包的标准记录器进行日志记录。
	ErrorLog *log.Logger

	// BaseContext可选地指定一个函数，该函数返回此服务器上传入请求的基本上下文。
	// 提供的侦听器是即将开始接受请求的特定侦听器。
	// 如果BaseContext为零，则默认为context。背景（）。
	// 如果为非nil，则必须返回非nil上下文。
	BaseContext func(net.Listener) context.Context

	// ConnConContext可选地指定一个函数，该函数修改用于新连接c的上下文。提供的ctx 
	// 是从基本上下文派生的，具有ServerContextKey 
	// 值。
	ConnContext func(ctx context.Context, c net.Conn) context.Context

	inShutdown atomicBool // 服务器关闭时为true 

	disableKeepAlives int32     // 以原子方式访问。
	nextProtoOnce     sync.Once // 保护设置http2_*init 
	nextProtoErr      error     // http2的结果。配置服务器如果使用

	mu         sync.Mutex
	listeners  map[*net.Listener]struct{}
	activeConn map[*conn]struct{}
	doneChan   chan struct{}
	onShutdown []func()
}

func (s *Server) getDoneChan() <-chan struct{} {
	s.mu.Lock()
	defer s.mu.Unlock()
	return s.getDoneChanLocked()
}

func (s *Server) getDoneChanLocked() chan struct{} {
	if s.doneChan == nil {
		s.doneChan = make(chan struct{})
	}
	return s.doneChan
}

func (s *Server) closeDoneChanLocked() {
	ch := s.getDoneChanLocked()
	select {
	case <-ch:
		// 已关闭。别再关门了。
	default:
		// 这里可以安全关闭。我们是唯一一个被s.mu保护的更近的
		// 。
		close(ch)
	}
}

// 关闭立即关闭所有活动网络。侦听器和任何
// 状态为StateNew、StateActive或StateIdle的连接。对于
// 正常关机，请使用关机。
// 
// Close不尝试关闭（甚至不知道）任何被劫持的连接，例如WebSocket。
// 
// Close返回关闭服务器的
// 基础侦听器时返回的任何错误。
func (srv *Server) Close() error {
	srv.inShutdown.setTrue()
	srv.mu.Lock()
	defer srv.mu.Unlock()
	srv.closeDoneChanLocked()
	err := srv.closeListenersLocked()
	for c := range srv.activeConn {
		c.rwc.Close()
		delete(srv.activeConn, c)
	}
	return err
}

// SHUTDOWNPOLINTERVALMAX是检查
// 服务器期间静止时的最大轮询间隔。关机。轮询从一个小的
// 间隔开始，然后返回到最大值。
// 理想情况下，我们可以找到一个不涉及轮询的解决方案，
// 但也不会有高运行时成本（并且
// 不涉及任何有争议的互斥），但这是留给读者的一个
// 练习。
const shutdownPollIntervalMax = 500 * time.Millisecond

// 关机在不中断任何
// 活动连接的情况下，优雅地关闭服务器。关机的工作原理是先关闭所有打开的
// 侦听器，然后关闭所有空闲连接，然后无限期地等待
// 连接返回空闲状态，然后关机。
// 如果提供的上下文在关闭完成之前过期，
// 关闭返回上下文错误，否则返回关闭服务器底层侦听器返回的任何
// 错误。
// 
// 调用Shutdown时，Serve、LISTENDSERVE和
// LISTENDSERVETLS立即返回ErrServerClosed。确保
// 程序没有退出，而是等待关机返回。
// 
// 关机不会试图关闭或等待被劫持的
// 连接，如WebSocket。如果需要，关机调用方应分别通知这些长期存在的关机连接，并等待它们关闭。有关
// 注册关机通知函数的方法，请参阅RegisterOnShutdown。
// 
// 一旦在服务器上调用了关机，它可能不会被重用；
// 以后对Serve等方法的调用将返回ErrServerClosed。
func (srv *Server) Shutdown(ctx context.Context) error {
	srv.inShutdown.setTrue()

	srv.mu.Lock()
	lnerr := srv.closeListenersLocked()
	srv.closeDoneChanLocked()
	for _, f := range srv.onShutdown {
		go f()
	}
	srv.mu.Unlock()

	pollIntervalBase := time.Millisecond
	nextPollInterval := func() time.Duration {
		// 增加10%的抖动。
		interval := pollIntervalBase + time.Duration(rand.Intn(int(pollIntervalBase/10)))
		// 下次加倍并夹紧。
		pollIntervalBase *= 2
		if pollIntervalBase > shutdownPollIntervalMax {
			pollIntervalBase = shutdownPollIntervalMax
		}
		return interval
	}

	timer := time.NewTimer(nextPollInterval())
	defer timer.Stop()
	for {
		if srv.closeIdleConns() && srv.numListeners() == 0 {
			return lnerr
		}
		select {
		case <-ctx.Done():
			return ctx.Err()
		case <-timer.C:
			timer.Reset(nextPollInterval())
		}
	}
}

// RegisterOnShutdown注册一个函数来调用Shutdown。
// 这可用于正常关闭具有
// 正在进行ALPN协议升级或已被劫持。
// 此函数应启动协议特定的正常关机，但不应等待关机完成。
func (srv *Server) RegisterOnShutdown(f func()) {
	srv.mu.Lock()
	srv.onShutdown = append(srv.onShutdown, f)
	srv.mu.Unlock()
}

func (s *Server) numListeners() int {
	s.mu.Lock()
	defer s.mu.Unlock()
	return len(s.listeners)
}

// closeIdleConns关闭所有空闲连接，并报告
// 服务器是否处于静止状态。
func (s *Server) closeIdleConns() bool {
	s.mu.Lock()
	defer s.mu.Unlock()
	quiescent := true
	for c := range s.activeConn {
		st, unixSec := c.getState()
		// 问题22682：将状态新连接视为
		// 如果我们在5秒内没有读取第一个请求的
		// 头，它们将处于空闲状态。
		if st == StateNew && unixSec < time.Now().Unix()-5 {
			st = StateIdle
		}
		if st != StateIdle || unixSec == 0 {
			// 假设unixSec==0意味着这是一个非常新的
			// 连接，尚未设置状态。
			quiescent = false
			continue
		}
		c.rwc.Close()
		delete(s.activeConn, c)
	}
	return quiescent
}

func (s *Server) closeListenersLocked() error {
	var err error
	for ln := range s.listeners {
		if cerr := (*ln).Close(); cerr != nil && err == nil {
			err = cerr
		}
	}
	return err
}

// ConnState表示客户端与服务器的连接状态。
// 由可选服务器使用。康纳特胡克。
type ConnState int

const (
	// StateNew表示一个新连接，该连接将立即发送请求。连接从这个
	// 状态开始，然后转换到StateActive或
	// StateClosed。
	StateNew ConnState = iota

	// StateActive表示已读取请求的1个或多个
	// 字节的连接。服务器。
	// StateActive的ConnState钩子在请求进入处理程序
	// 之前触发，在请求被
	// 处理之前不会再次触发。处理请求后，状态
	// 将转换为StateClosed、StateHijacked或StateIdle。
	// 对于HTTP/2，StateActive在从零
	// 转换为一个活动请求时触发，并且只有在所有
	// 活动请求完成后才会转换。这意味着ConnState 
	// 不能用于按请求执行工作；ConnState只注意
	// 连接的整体状态。
	StateActive

	// StateIdle表示已完成
	// 处理请求并处于保持活动状态的连接，正在等待
	// 等待新请求。连接从StateIdle 
	// 转换为StateActive或StateClosed。
	StateIdle

	// StateHijacked表示被劫持的连接。这是一个终端状态。它不会转换为StateClosed。
	StateHijacked

	// StateClosed表示一个关闭的连接。这是一个终端状态。被劫持的连接不
	// 转换为状态关闭。
	StateClosed
)

var stateName = map[ConnState]string{
	StateNew:      "new",
	StateActive:   "active",
	StateIdle:     "idle",
	StateHijacked: "hijacked",
	StateClosed:   "closed",
}

func (c ConnState) String() string {
	return stateName[c]
}

// serverHandler委托给服务器的处理程序或
// DefaultServeMux，并处理“选项*”请求。
type serverHandler struct {
	srv *Server
}

func (sh serverHandler) ServeHTTP(rw ResponseWriter, req *Request) {
	handler := sh.srv.Handler
	if handler == nil {
		handler = DefaultServeMux
	}
	if req.RequestURI == "*" && req.Method == "OPTIONS" {
		handler = globalOptionsHandler{}
	}

	if req.URL != nil && strings.Contains(req.URL.RawQuery, ";") {
		var allowQuerySemicolonsInUse int32
		req = req.WithContext(context.WithValue(req.Context(), silenceSemWarnContextKey, func() {
			atomic.StoreInt32(&allowQuerySemicolonsInUse, 1)
		}))
		defer func() {
			if atomic.LoadInt32(&allowQuerySemicolonsInUse) == 0 {
				sh.srv.logf("http: URL query contains semicolon, which is no longer a supported separator; parts of the query may be stripped when parsed; see golang.org/issue/25192")
			}
		}()
	}

	handler.ServeHTTP(rw, req)
}

var silenceSemWarnContextKey = &contextKey{"silence-semicolons"}

// AllowQuerySamicolons通过将URL查询中的任何
// unscaped分号转换为符号，并调用处理程序h，返回一个处理程序，该处理程序为请求提供服务。
// 
// 这将恢复在
// 分号和符号上拆分查询参数的pre Go 1.17行为。（见golang.org/issue/25192）。请注意，这种行为与许多代理的行为不匹配，这种不匹配可能会导致
// 安全问题。
// 
// 请求前应调用AllowQuerySemicolons。ParseForm被称为。
func AllowQuerySemicolons(h Handler) Handler {
	return HandlerFunc(func(w ResponseWriter, r *Request) {
		if silenceSemicolonsWarning, ok := r.Context().Value(silenceSemWarnContextKey).(func()); ok {
			silenceSemicolonsWarning()
		}
		if strings.Contains(r.URL.RawQuery, ";") {
			r2 := new(Request)
			*r2 = *r
			r2.URL = new(url.URL)
			*r2.URL = *r.URL
			r2.URL.RawQuery = strings.ReplaceAll(r.URL.RawQuery, ";", "&")
			h.ServeHTTP(w, r2)
		} else {
			h.ServeHTTP(w, r)
		}
	})
}

// ListendServe监听TCP网络地址srv。Addr和
// 调用用于处理传入连接上的请求。
// 已将接受的连接配置为启用TCP保持有效。
// 
// 如果srv。Addr为空，使用“：http”。
// 
// ListendServe始终返回非零错误。关机或关闭后，
// 返回错误为ErrServerClosed。
func (srv *Server) ListenAndServe() error {
	if srv.shuttingDown() {
		return ErrServerClosed
	}
	addr := srv.Addr
	if addr == "" {
		addr = ":http"
	}
	ln, err := net.Listen("tcp", addr)
	if err != nil {
		return err
	}
	return srv.Serve(ln)
}

var testHookServerServe func(*Server, net.Listener) // 如果非零，则使用

// 应报告服务器是否关闭。Serve应该配置
// 自动HTTP/2。（设置srv.TLSNextProto映射）
func (srv *Server) shouldConfigureHTTP2ForServe() bool {
	if srv.TLSConfig == nil {
		// 与Go 1.6的兼容性：
		// 如果没有TLSConfig，用户可能只是
		// 没有在http上设置它。服务器，但已将其传递给
		// tls。NewListener并将其传递给该听众服务。
		// 所以我们应该配置HTTP/2（设置srv.TLSNextProto）
		// 以防侦听器返回“h2”*tls。Conn.
		return true
	}
	// 用户在其http上指定了一个TLSConfig。服务器
	// 在这种情况下，仅在其tls可用时配置HTTP/2。Config 
	// 明确提到“h2”。否则就是http2。ConfigureServer 
	// 将修改tls。配置添加，但他们可能已经通过了这个tls。配置到tls。NewListener。如果他们真的这么做了，那就太晚了。这只会有潜在的快感。
	// 见第15908期。
	return strSliceContains(srv.TLSConfig.NextProtos, http2NextProtoTLS)
}

// ErrServerClosed是在调用Shutdown或Close后，服务器的service、ServeTLS、listendandserve、
// 和listendandservetls方法返回的。
var ErrServerClosed = errors.New("http: Server closed")

// service接受侦听器l上的传入连接，为每个连接创建一个
// 新的服务goroutine。服务goroutines read requests和
// 然后调用srv。处理者回复他们。
// 
// HTTP/2支持仅在侦听器返回*tls时启用。Conn 
// 连接，它们在TLS 
// 配置中配置为“h2”。下一本。
// 
// Serve始终返回非零错误并关闭l。
// 关闭或关闭后，返回的错误为ErrServerClosed。
func (srv *Server) Serve(l net.Listener) error {
	if fn := testHookServerServe; fn != nil {
		fn(srv, l) // call hook with unwrapped listener 
	}

	origListener := l
	l = &onceCloseListener{Listener: l}
	defer l.Close()

	if err := srv.setupHTTP2_Serve(); err != nil {
		return err
	}

	if !srv.trackListener(&l, true) {
		return ErrServerClosed
	}
	defer srv.trackListener(&l, false)

	baseCtx := context.Background()
	if srv.BaseContext != nil {
		baseCtx = srv.BaseContext(origListener)
		if baseCtx == nil {
			panic("BaseContext returned a nil context")
		}
	}

	var tempDelay time.Duration // accept failure 

	ctx := context.WithValue(baseCtx, ServerContextKey, srv)
	for {
		rw, err := l.Accept()
		if err != nil {
			select {
			case <-srv.getDoneChan():
				return ErrServerClosed
			default:
			}
			if ne, ok := err.(net.Error); ok && ne.Temporary() {
				if tempDelay == 0 {
					tempDelay = 5 * time.Millisecond
				} else {
					tempDelay *= 2
				}
				if max := 1 * time.Second; tempDelay > max {
					tempDelay = max
				}
				srv.logf("http: Accept error: %v; retrying in %v", err, tempDelay)
				time.Sleep(tempDelay)
				continue
			}
			return err
		}
		connCtx := ctx
		if cc := srv.ConnContext; cc != nil {
			connCtx = cc(connCtx, rw)
			if connCtx == nil {
				panic("ConnContext returned nil")
			}
		}
		tempDelay = 0
		c := srv.newConn(rw)
		c.setState(c.rwc, StateNew, runHooks) // service可以返回
		go c.serve(connCtx)
	}
}

// ServeTLS接受侦听器l上的传入连接，为每个侦听器创建一个
// 新的服务goroutine。服务goroutines执行TLS 
// 设置，然后读取请求，调用srv。处理者回复他们。
// 
// 如果服务器的
// 服务器提供包含证书和匹配私钥的文件。证书或TLSConfig。已填充GetCertificate。
// TLSConfig都不存在，则必须为
// 如果证书由证书颁发机构签署，则
// 证书文件应该是服务器证书、
// 任何中间证书和CA证书的串联。
// 
// ServeTLS始终返回非零错误。关机或关闭后，
// 返回的错误为ErrServerClosed。
func (srv *Server) ServeTLS(l net.Listener, certFile, keyFile string) error {
	// 在srv之前设置HTTP/2。服务，初始化srv。TLSConfig 
	// 在我们克隆它并创建TLS侦听器之前。
	if err := srv.setupHTTP2_ServeTLS(); err != nil {
		return err
	}

	config := cloneTLSConfig(srv.TLSConfig)
	if !strSliceContains(config.NextProtos, "http/1.1") {
		config.NextProtos = append(config.NextProtos, "http/1.1")
	}

	configHasCert := len(config.Certificates) > 0 || config.GetCertificate != nil
	if !configHasCert || certFile != "" || keyFile != "" {
		var err error
		config.Certificates = make([]tls.Certificate, 1)
		config.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile)
		if err != nil {
			return err
		}
	}

	tlsListener := tls.NewListener(l, config)
	return srv.Serve(tlsListener)
}

// trackListener添加或删除网络。跟踪
// 侦听器集的侦听器。
// 
// 我们在映射集中存储一个指向接口的指针，以防
// net。听众是不可比的。这是安全的，因为我们只通过Serve调用
// trackListener，并且可以跟踪并延迟取消跟踪同一个
// 指向本地变量的指针。我们永远不需要将
// 侦听器与另一个调用方进行比较。
// 
// 它报告服务器是否仍在运行（而不是关闭或关闭）。
func (s *Server) trackListener(ln *net.Listener, add bool) bool {
	s.mu.Lock()
	defer s.mu.Unlock()
	if s.listeners == nil {
		s.listeners = make(map[*net.Listener]struct{})
	}
	if add {
		if s.shuttingDown() {
			return false
		}
		s.listeners[ln] = struct{}{}
	} else {
		delete(s.listeners, ln)
	}
	return true
}

func (s *Server) trackConn(c *conn, add bool) {
	s.mu.Lock()
	defer s.mu.Unlock()
	if s.activeConn == nil {
		s.activeConn = make(map[*conn]struct{})
	}
	if add {
		s.activeConn[c] = struct{}{}
	} else {
		delete(s.activeConn, c)
	}
}

func (s *Server) idleTimeout() time.Duration {
	if s.IdleTimeout != 0 {
		return s.IdleTimeout
	}
	return s.ReadTimeout
}

func (s *Server) readHeaderTimeout() time.Duration {
	if s.ReadHeaderTimeout != 0 {
		return s.ReadHeaderTimeout
	}
	return s.ReadTimeout
}

func (s *Server) doKeepAlives() bool {
	return atomic.LoadInt32(&s.disableKeepAlives) == 0 && !s.shuttingDown()
}

func (s *Server) shuttingDown() bool {
	return s.inShutdown.isSet()
}

// SetKeepAlivesEnabled控制是否启用HTTP保持有效。
// 默认情况下，始终启用“保持有效”。只有非常
// 资源受限的环境或处于
// 关闭过程中的服务器才应禁用它们。
func (srv *Server) SetKeepAlivesEnabled(v bool) {
	if v {
		atomic.StoreInt32(&srv.disableKeepAlives, 0)
		return
	}
	atomic.StoreInt32(&srv.disableKeepAlives, 1)

	// 关闭空闲的HTTP/1连接：
	srv.closeIdleConns()

	// TODO:问题26303：HTTP/2连接空闲后立即关闭。
}

func (s *Server) logf(format string, args ...any) {
	if s.ErrorLog != nil {
		s.ErrorLog.Printf(format, args...)
	} else {
		log.Printf(format, args...)
	}
}

// logf通过ServerContextKey打印到与请求r相关的*服务器的错误日志
// 中。如果没有关联的服务器，或者如果ErrorLog 
// 为nil，则通过日志包的标准记录器完成日志记录。
func logf(r *Request, format string, args ...any) {
	s, _ := r.Context().Value(ServerContextKey).(*Server)
	if s != nil && s.ErrorLog != nil {
		s.ErrorLog.Printf(format, args...)
	} else {
		log.Printf(format, args...)
	}
}

// listendandserve监听TCP网络地址addr，然后调用
// Serve with handler来处理传入连接的请求。
// 已将接受的连接配置为启用TCP保持有效。
// 
// 处理程序通常为nil，在这种情况下使用DefaultServeMux。
// 
// ListendServe始终返回非零错误。
func ListenAndServe(addr string, handler Handler) error {
	server := &Server{Addr: addr, Handler: handler}
	return server.ListenAndServe()
}

// ListendServeTls的行为与ListendServeTs相同，只是它需要HTTPS连接。此外，必须提供包含证书和
// 匹配服务器私钥的文件。如果证书
// 由证书颁发机构签名，则证书文件应为服务器证书、任何中间证书和CA证书的串联
// 文件。
func ListenAndServeTLS(addr, certFile, keyFile string, handler Handler) error {
	server := &Server{Addr: addr, Handler: handler}
	return server.ListenAndServeTLS(certFile, keyFile)
}

// ListendServetls监听TCP网络地址srv。Addr和
// 然后调用servlet来处理传入TLS连接上的请求。
// 已将接受的连接配置为启用TCP保持有效。
// 
// 如果服务器的TLSConfig。证书
// 或TLSConfig。已填充GetCertificate。如果证书是由证书颁发机构签署的
// 证书文件应该是
// 连接服务器的证书、任何中间产品和
// CA的证书。
// 
// 如果srv。地址为空，使用“：https”。
// 
// ListendServetls始终返回非零错误。关机或
// 关闭后，返回的错误为ErrServerClosed。
func (srv *Server) ListenAndServeTLS(certFile, keyFile string) error {
	if srv.shuttingDown() {
		return ErrServerClosed
	}
	addr := srv.Addr
	if addr == "" {
		addr = ":https"
	}

	ln, err := net.Listen("tcp", addr)
	if err != nil {
		return err
	}

	defer ln.Close()

	return srv.ServeTLS(ln, certFile, keyFile)
}

// setupHTTP2_ServeTLS在
// srv上有条件地配置HTTP/2，并报告是否存在设置错误。如果是
// 由于策略原因未配置，则返回nil。
func (srv *Server) setupHTTP2_ServeTLS() error {
	srv.nextProtoOnce.Do(srv.onceSetNextProtoDefaults)
	return srv.nextProtoErr
}

// setupHTTP2_-Serve是从（*Server）调用的。SERVICE并有条件地
// 在srv上使用比
// 更保守的策略配置HTTP/2，因为SERVICE是在tls之后调用的。听着，
// 可能会同时被调用。有关服务，请参阅shouldConfigureHttp2。
// 
// 名为TestTransportAutomaticHTTP2*和
// TestConcurrentServerServe的测试在服务器_测试中。去展示一些
// 支持的用例和动机。
func (srv *Server) setupHTTP2_Serve() error {
	srv.nextProtoOnce.Do(srv.onceSetNextProtoDefaults_Serve)
	return srv.nextProtoErr
}

func (srv *Server) onceSetNextProtoDefaults_Serve() {
	if srv.shouldConfigureHTTP2ForServe() {
		srv.onceSetNextProtoDefaults()
	}
}

// 如果用户没有配置
// 则oncetnextprotodefaults配置HTTP/2。（通过设置srv.TLSNextProto non nil）
// 只能通过srv调用它。nextProtoOnce（使用srv.setupHTTP2_*）。
func (srv *Server) onceSetNextProtoDefaults() {
	if omitBundledHTTP2 || godebug.Get("http2server") == "0" {
		return
	}
	// 如果用户没有配置其TLSNextProto映射，则默认启用HTTP/2。
	if srv.TLSNextProto == nil {
		conf := &http2Server{
			NewWriteScheduler: func() http2WriteScheduler { return http2NewPriorityWriteScheduler(nil) },
		}
		srv.nextProtoErr = http2ConfigureServer(srv, conf)
	}
}

// TimeoutHandler返回在给定时间限制下运行h的处理程序。
// 
// 新处理程序调用h.ServeHTTP来处理每个请求，但是如果
// 调用的运行时间超过其时间限制，则处理程序将以
// 503服务不可用错误及其正文中的给定消息进行响应。
// /（如果消息为空，将发送一条合适的默认消息。）
// 在这样一个超时之后，h对其响应writer的写入将返回
// ErrHandlerTimeout。
// 
// TimeoutHandler支持Pusher接口，但不支持
// Hicker或Flusher接口。
func TimeoutHandler(h Handler, dt time.Duration, msg string) Handler {
	return &timeoutHandler{
		handler: h,
		body:    msg,
		dt:      dt,
	}
}

// ErrHandlerTimeout在已超时的处理程序中的ResponseWriter写入调用返回
// 。
var ErrHandlerTimeout = errors.New("http: Handler timeout")

type timeoutHandler struct {
	handler Handler
	body    string
	dt      time.Duration

	// 设置后，不会创建任何上下文，而是使用此上下文
	// 来代替。
	testContext context.Context
}

func (h *timeoutHandler) errorBody() string {
	if h.body != "" {
		return h.body
	}
	return "<html><head><title>Timeout</title></head><body><h1>Timeout</h1></body></html>"
}

func (h *timeoutHandler) ServeHTTP(w ResponseWriter, r *Request) {
	ctx := h.testContext
	if ctx == nil {
		var cancelCtx context.CancelFunc
		ctx, cancelCtx = context.WithTimeout(r.Context(), h.dt)
		defer cancelCtx()
	}
	r = r.WithContext(ctx)
	done := make(chan struct{})
	tw := &timeoutWriter{
		w:   w,
		h:   make(Header),
		req: r,
	}
	panicChan := make(chan any, 1)
	go func() {
		defer func() {
			if p := recover(); p != nil {
				panicChan <- p
			}
		}()
		h.handler.ServeHTTP(tw, r)
		close(done)
	}()
	select {
	case p := <-panicChan:
		panic(p)
	case <-done:
		tw.mu.Lock()
		defer tw.mu.Unlock()
		dst := w.Header()
		for k, vv := range tw.h {
			dst[k] = vv
		}
		if !tw.wroteHeader {
			tw.code = StatusOK
		}
		w.WriteHeader(tw.code)
		w.Write(tw.wbuf.Bytes())
	case <-ctx.Done():
		tw.mu.Lock()
		defer tw.mu.Unlock()
		switch err := ctx.Err(); err {
		case context.DeadlineExceeded:
			w.WriteHeader(StatusServiceUnavailable)
			io.WriteString(w, h.errorBody())
			tw.err = ErrHandlerTimeout
		default:
			w.WriteHeader(StatusServiceUnavailable)
			tw.err = err
		}
	}
}

type timeoutWriter struct {
	w    ResponseWriter
	h    Header
	wbuf bytes.Buffer
	req  *Request

	mu          sync.Mutex
	err         error
	wroteHeader bool
	code        int
}

var _ Pusher = (*timeoutWriter)(nil)

// Push实现Pusher接口。
func (tw *timeoutWriter) Push(target string, opts *PushOptions) error {
	if pusher, ok := tw.w.(Pusher); ok {
		return pusher.Push(target, opts)
	}
	return ErrNotSupported
}

func (tw *timeoutWriter) Header() Header { return tw.h }

func (tw *timeoutWriter) Write(p []byte) (int, error) {
	tw.mu.Lock()
	defer tw.mu.Unlock()
	if tw.err != nil {
		return 0, tw.err
	}
	if !tw.wroteHeader {
		tw.writeHeaderLocked(StatusOK)
	}
	return tw.wbuf.Write(p)
}

func (tw *timeoutWriter) writeHeaderLocked(code int) {
	checkWriteHeaderCode(code)

	switch {
	case tw.err != nil:
		return
	case tw.wroteHeader:
		if tw.req != nil {
			caller := relevantCaller()
			logf(tw.req, "http: superfluous response.WriteHeader call from %s (%s:%d)", caller.Function, path.Base(caller.File), caller.Line)
		}
	default:
		tw.wroteHeader = true
		tw.code = code
	}
}

func (tw *timeoutWriter) WriteHeader(code int) {
	tw.mu.Lock()
	defer tw.mu.Unlock()
	tw.writeHeaderLocked(code)
}

// onceCloseListener包装一张网。侦听器，保护它不受
// 多个关闭呼叫的影响。
type onceCloseListener struct {
	net.Listener
	once     sync.Once
	closeErr error
}

func (oc *onceCloseListener) Close() error {
	oc.once.Do(oc.close)
	return oc.closeErr
}

func (oc *onceCloseListener) close() { oc.closeErr = oc.Listener.Close() }

// globalOptionsHandler响应“选项*”请求。
type globalOptionsHandler struct{}

func (globalOptionsHandler) ServeHTTP(w ResponseWriter, r *Request) {
	w.Header().Set("Content-Length", "0")
	if r.ContentLength != 0 {
		// 读取高达4KB的选项正文（如
		// 规范中所述，保留供将来使用），但任何
		// 超过该值都被视为浪费服务器资源
		// （或攻击），我们中止并关闭连接，
		// 感谢MaxBytesReader的EOF行为。
		mb := MaxBytesReader(w, r.Body, 4<<10)
		io.Copy(io.Discard, mb)
	}
}

// initALPNRequest是一个HTTP处理程序，用于初始化其*请求中的某些未初始化字段。这种部分初始化的
// 请求来自ALPN协议处理程序。
type initALPNRequest struct {
	ctx context.Context
	c   *tls.Conn
	h   serverHandler
}

// BaseContext是一个已导出但未经广告的http。Handler方法
// 被x/net/http2识别以传递上下文；TLSNextProto 
// API早于上下文支持，因此我们只能使用
// 接口。
func (h initALPNRequest) BaseContext() context.Context { return h.ctx }

func (h initALPNRequest) ServeHTTP(rw ResponseWriter, req *Request) {
	if req.TLS == nil {
		req.TLS = &tls.ConnectionState{}
		*req.TLS = h.c.ConnectionState()
	}
	if req.Body == nil {
		req.Body = NoBody
	}
	if req.RemoteAddr == "" {
		req.RemoteAddr = h.c.RemoteAddr().String()
	}
	h.h.ServeHTTP(rw, req)
}

// loggingConn用于调试。
type loggingConn struct {
	name string
	net.Conn
}

var (
	uniqNameMu   sync.Mutex
	uniqNameNext = make(map[string]int)
)

func newLoggingConn(baseName string, c net.Conn) net.Conn {
	uniqNameMu.Lock()
	defer uniqNameMu.Unlock()
	uniqNameNext[baseName]++
	return &loggingConn{
		name: fmt.Sprintf("%s-%d", baseName, uniqNameNext[baseName]),
		Conn: c,
	}
}

func (c *loggingConn) Write(p []byte) (n int, err error) {
	log.Printf("%s.Write(%d) = ....", c.name, len(p))
	n, err = c.Conn.Write(p)
	log.Printf("%s.Write(%d) = %d, %v", c.name, len(p), n, err)
	return
}

func (c *loggingConn) Read(p []byte) (n int, err error) {
	log.Printf("%s.Read(%d) = ....", c.name, len(p))
	n, err = c.Conn.Read(p)
	log.Printf("%s.Read(%d) = %d, %v", c.name, len(p), n, err)
	return
}

func (c *loggingConn) Close() (err error) {
	log.Printf("%s.Close() = ...", c.name)
	err = c.Conn.Close()
	log.Printf("%s.Close() = %v", c.name, err)
	return
}

// checkConnErrorWriter写入c.rwc并将任何写入错误记录到c.werr。
// 它只包含一个字段（以及一个指针字段），因此它不需要额外分配就可以放入接口值中。
type checkConnErrorWriter struct {
	c *conn
}

func (w checkConnErrorWriter) Write(p []byte) (n int, err error) {
	n, err = w.c.rwc.Write(p)
	if err != nil && w.c.werr == nil {
		w.c.werr = err
		w.c.cancelCtx()
	}
	return
}

func numLeadingCRorLF(v []byte) (n int) {
	for _, b := range v {
		if b == '\r' || b == '\n' {
			n++
			continue
		}
		break
	}
	return

}

func strSliceContains(ss []string, s string) bool {
	for _, v := range ss {
		if v == s {
			return true
		}
	}
	return false
}

// tlsRecordHeaderLooksLikeHTTP报告TLS记录头
// 看起来可能是一个错误的明文HTTP请求。
func tlsRecordHeaderLooksLikeHTTP(hdr [5]byte) bool {
	switch string(hdr[:]) {
	case "GET /", "HEAD ", "POST ", "PUT /", "OPTIO":
		return true
	}
	return false
}

// MaxBytesHandler返回一个处理程序，该处理程序使用其响应编写器和请求运行h。尸体被MaxBytesReader包裹着。
func MaxBytesHandler(h Handler, n int64) Handler {
	return HandlerFunc(func(w ResponseWriter, r *Request) {
		r2 := *r
		r2.Body = MaxBytesReader(w, r.Body, n)
		h.ServeHTTP(w, &r2)
	})
}
